blob: a4380d134c979dfe00d5ef17b85d6ee34695dad8 [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
sewardjc913c8e2014-05-15 13:50:47 +0000130#elif (defined(__MINGW32__) && !defined(__MINGW64__)) \
131 || defined(__CYGWIN32__) \
sewardj6e9de462011-06-28 07:25:29 +0000132 || (defined(_WIN32) && defined(_M_IX86))
bart7f489812010-08-27 10:05:27 +0000133# define PLAT_x86_win32 1
sewardjc913c8e2014-05-15 13:50:47 +0000134#elif defined(__MINGW64__) \
135 || (defined(_WIN64) && defined(_M_X64))
bartaaaf21d2013-08-25 06:10:24 +0000136# define PLAT_amd64_win64 1
sewardj59570ff2010-01-01 11:59:33 +0000137#elif defined(__linux__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000138# define PLAT_x86_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000139#elif defined(__linux__) && defined(__x86_64__)
njnf76d27a2009-05-28 01:53:07 +0000140# define PLAT_amd64_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_ppc32_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000143#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000144# define PLAT_ppc64_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000145#elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__)
sewardj59570ff2010-01-01 11:59:33 +0000146# define PLAT_arm_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000147#elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__)
148# define PLAT_arm64_linux 1
sewardjb5b87402011-03-07 16:05:35 +0000149#elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
150# define PLAT_s390x_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000151#elif defined(__linux__) && defined(__mips__) && (__mips==64)
petarj4df0bfc2013-02-27 23:17:33 +0000152# define PLAT_mips64_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000153#elif defined(__linux__) && defined(__mips__) && (__mips!=64)
sewardj5db15402012-06-07 09:13:21 +0000154# define PLAT_mips32_linux 1
njnf76d27a2009-05-28 01:53:07 +0000155#else
sewardjf5c1a7f2006-10-17 01:32:48 +0000156/* If we're not compiling for our target platform, don't generate
sewardj0ec07f32006-01-12 12:32:32 +0000157 any inline asms. */
sewardj0ec07f32006-01-12 12:32:32 +0000158# if !defined(NVALGRIND)
159# define NVALGRIND 1
160# endif
161#endif
162
163
njn30d76c62005-06-18 15:07:39 +0000164/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000165/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
166/* in here of use to end-users -- skip to the next section. */
njn30d76c62005-06-18 15:07:39 +0000167/* ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000168
bart575ce8e2011-05-15 07:04:03 +0000169/*
170 * VALGRIND_DO_CLIENT_REQUEST(): a statement that invokes a Valgrind client
171 * request. Accepts both pointers and integers as arguments.
172 *
sewardj4b3a7422011-10-24 13:21:57 +0000173 * VALGRIND_DO_CLIENT_REQUEST_STMT(): a statement that invokes a Valgrind
174 * client request that does not return a value.
175
bart575ce8e2011-05-15 07:04:03 +0000176 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
sewardj4b3a7422011-10-24 13:21:57 +0000177 * client request and whose value equals the client request result. Accepts
178 * both pointers and integers as arguments. Note that such calls are not
179 * necessarily pure functions -- they may have side effects.
bart575ce8e2011-05-15 07:04:03 +0000180 */
181
182#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, \
183 _zzq_request, _zzq_arg1, _zzq_arg2, \
184 _zzq_arg3, _zzq_arg4, _zzq_arg5) \
florian17dfe1a2011-10-22 15:04:05 +0000185 do { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default), \
bart575ce8e2011-05-15 07:04:03 +0000186 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
florian17dfe1a2011-10-22 15:04:05 +0000187 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
bart575ce8e2011-05-15 07:04:03 +0000188
sewardj4b3a7422011-10-24 13:21:57 +0000189#define VALGRIND_DO_CLIENT_REQUEST_STMT(_zzq_request, _zzq_arg1, \
190 _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
191 do { (void) VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
192 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
193 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
194
sewardj0ec07f32006-01-12 12:32:32 +0000195#if defined(NVALGRIND)
njn26aba4d2005-05-16 13:31:23 +0000196
197/* Define NVALGRIND to completely remove the Valgrind magic sequence
sewardj0ec07f32006-01-12 12:32:32 +0000198 from the compiled code (analogous to NDEBUG's effects on
199 assert()) */
bart575ce8e2011-05-15 07:04:03 +0000200#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
201 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000202 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000203 (_zzq_default)
njn26aba4d2005-05-16 13:31:23 +0000204
sewardj0ec07f32006-01-12 12:32:32 +0000205#else /* ! NVALGRIND */
nethercotee90c6832004-10-18 18:07:49 +0000206
sewardj0ec07f32006-01-12 12:32:32 +0000207/* The following defines the magic code sequences which the JITter
208 spots and handles magically. Don't look too closely at them as
209 they will rot your brain.
210
211 The assembly code sequences for all architectures is in this one
212 file. This is because this file must be stand-alone, and we don't
213 want to have multiple files.
214
215 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
216 value gets put in the return slot, so that everything works when
217 this is executed not under Valgrind. Args are passed in a memory
218 block, and so there's no intrinsic limit to the number that could
sewardj9af10a12006-02-01 14:59:42 +0000219 be passed, but it's currently five.
nethercotee90c6832004-10-18 18:07:49 +0000220
nethercote54265442004-10-26 12:56:58 +0000221 The macro args are:
222 _zzq_rlval result lvalue
223 _zzq_default default value (result returned when running on real CPU)
224 _zzq_request request code
sewardj9af10a12006-02-01 14:59:42 +0000225 _zzq_arg1..5 request params
nethercote54265442004-10-26 12:56:58 +0000226
sewardj0ec07f32006-01-12 12:32:32 +0000227 The other two macros are used to support function wrapping, and are
sewardjd68ac3e2006-01-20 14:31:57 +0000228 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
229 guest's NRADDR pseudo-register and whatever other information is
230 needed to safely run the call original from the wrapper: on
231 ppc64-linux, the R2 value at the divert point is also needed. This
232 information is abstracted into a user-visible type, OrigFn.
233
234 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
235 guest, but guarantees that the branch instruction will not be
236 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
237 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
238 complete inline asm, since it needs to be combined with more magic
239 inline asm stuff to be useful.
nethercotee90c6832004-10-18 18:07:49 +0000240*/
241
njnf76d27a2009-05-28 01:53:07 +0000242/* ------------------------- x86-{linux,darwin} ---------------- */
sewardjde4a4ab2005-03-23 13:10:32 +0000243
sewardj520a03a2010-10-07 10:46:15 +0000244#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
sewardj60227842010-10-07 10:00:56 +0000245 || (defined(PLAT_x86_win32) && defined(__GNUC__))
sewardjc8858442006-01-20 15:17:20 +0000246
247typedef
248 struct {
249 unsigned int nraddr; /* where's the code? */
250 }
251 OrigFn;
252
sewardj0ec07f32006-01-12 12:32:32 +0000253#define __SPECIAL_INSTRUCTION_PREAMBLE \
254 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000255 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000256
bart575ce8e2011-05-15 07:04:03 +0000257#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
258 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000259 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000260 __extension__ \
261 ({volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000262 volatile unsigned int _zzq_result; \
263 _zzq_args[0] = (unsigned int)(_zzq_request); \
264 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
265 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
266 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
267 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000268 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000269 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
270 /* %EDX = client_request ( %EAX ) */ \
271 "xchgl %%ebx,%%ebx" \
272 : "=d" (_zzq_result) \
273 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
274 : "cc", "memory" \
275 ); \
bart575ce8e2011-05-15 07:04:03 +0000276 _zzq_result; \
277 })
sewardj2c48c7b2005-11-29 13:05:56 +0000278
sewardjc8858442006-01-20 15:17:20 +0000279#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
280 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
281 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000282 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
283 /* %EAX = guest_NRADDR */ \
284 "xchgl %%ecx,%%ecx" \
285 : "=a" (__addr) \
286 : \
287 : "cc", "memory" \
288 ); \
sewardjc8858442006-01-20 15:17:20 +0000289 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000290 }
sewardj0ec07f32006-01-12 12:32:32 +0000291
292#define VALGRIND_CALL_NOREDIR_EAX \
293 __SPECIAL_INSTRUCTION_PREAMBLE \
294 /* call-noredir *%EAX */ \
295 "xchgl %%edx,%%edx\n\t"
florianbb913cd2012-08-28 16:50:39 +0000296
297#define VALGRIND_VEX_INJECT_IR() \
298 do { \
299 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
300 "xchgl %%edi,%%edi\n\t" \
301 : : : "cc", "memory" \
302 ); \
303 } while (0)
304
sewardj60227842010-10-07 10:00:56 +0000305#endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__) */
bart7f489812010-08-27 10:05:27 +0000306
307/* ------------------------- x86-Win32 ------------------------- */
308
309#if defined(PLAT_x86_win32) && !defined(__GNUC__)
310
311typedef
312 struct {
313 unsigned int nraddr; /* where's the code? */
314 }
315 OrigFn;
316
317#if defined(_MSC_VER)
318
319#define __SPECIAL_INSTRUCTION_PREAMBLE \
320 __asm rol edi, 3 __asm rol edi, 13 \
321 __asm rol edi, 29 __asm rol edi, 19
322
bart575ce8e2011-05-15 07:04:03 +0000323#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
324 _zzq_default, _zzq_request, \
bart7f489812010-08-27 10:05:27 +0000325 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000326 valgrind_do_client_request_expr((uintptr_t)(_zzq_default), \
327 (uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1), \
328 (uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3), \
329 (uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5))
330
331static __inline uintptr_t
332valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request,
333 uintptr_t _zzq_arg1, uintptr_t _zzq_arg2,
334 uintptr_t _zzq_arg3, uintptr_t _zzq_arg4,
335 uintptr_t _zzq_arg5)
336{
337 volatile uintptr_t _zzq_args[6];
338 volatile unsigned int _zzq_result;
339 _zzq_args[0] = (uintptr_t)(_zzq_request);
340 _zzq_args[1] = (uintptr_t)(_zzq_arg1);
341 _zzq_args[2] = (uintptr_t)(_zzq_arg2);
342 _zzq_args[3] = (uintptr_t)(_zzq_arg3);
343 _zzq_args[4] = (uintptr_t)(_zzq_arg4);
344 _zzq_args[5] = (uintptr_t)(_zzq_arg5);
345 __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default
346 __SPECIAL_INSTRUCTION_PREAMBLE
347 /* %EDX = client_request ( %EAX ) */
348 __asm xchg ebx,ebx
349 __asm mov _zzq_result, edx
350 }
351 return _zzq_result;
352}
bart7f489812010-08-27 10:05:27 +0000353
354#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
355 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
356 volatile unsigned int __addr; \
357 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
358 /* %EAX = guest_NRADDR */ \
359 __asm xchg ecx,ecx \
360 __asm mov __addr, eax \
361 } \
362 _zzq_orig->nraddr = __addr; \
363 }
364
365#define VALGRIND_CALL_NOREDIR_EAX ERROR
366
florianbb913cd2012-08-28 16:50:39 +0000367#define VALGRIND_VEX_INJECT_IR() \
368 do { \
369 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
370 __asm xchg edi,edi \
371 } \
372 } while (0)
373
bart7f489812010-08-27 10:05:27 +0000374#else
375#error Unsupported compiler.
376#endif
377
378#endif /* PLAT_x86_win32 */
sewardj0ec07f32006-01-12 12:32:32 +0000379
njnf76d27a2009-05-28 01:53:07 +0000380/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000381
sewardjc913c8e2014-05-15 13:50:47 +0000382#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \
383 || (defined(PLAT_amd64_win64) && defined(__GNUC__))
sewardjc8858442006-01-20 15:17:20 +0000384
385typedef
386 struct {
387 unsigned long long int nraddr; /* where's the code? */
388 }
389 OrigFn;
390
sewardj0ec07f32006-01-12 12:32:32 +0000391#define __SPECIAL_INSTRUCTION_PREAMBLE \
392 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000393 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000394
bart575ce8e2011-05-15 07:04:03 +0000395#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
396 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000397 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000398 __extension__ \
399 ({ volatile unsigned long long int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000400 volatile unsigned long long int _zzq_result; \
401 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
402 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
403 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
404 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
405 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000406 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000407 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
408 /* %RDX = client_request ( %RAX ) */ \
409 "xchgq %%rbx,%%rbx" \
410 : "=d" (_zzq_result) \
411 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
412 : "cc", "memory" \
413 ); \
bart575ce8e2011-05-15 07:04:03 +0000414 _zzq_result; \
415 })
sewardj0ec07f32006-01-12 12:32:32 +0000416
sewardjc8858442006-01-20 15:17:20 +0000417#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
418 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
419 volatile unsigned long long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000420 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
421 /* %RAX = guest_NRADDR */ \
422 "xchgq %%rcx,%%rcx" \
423 : "=a" (__addr) \
424 : \
425 : "cc", "memory" \
426 ); \
sewardjc8858442006-01-20 15:17:20 +0000427 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000428 }
429
430#define VALGRIND_CALL_NOREDIR_RAX \
431 __SPECIAL_INSTRUCTION_PREAMBLE \
432 /* call-noredir *%RAX */ \
433 "xchgq %%rdx,%%rdx\n\t"
florianbb913cd2012-08-28 16:50:39 +0000434
435#define VALGRIND_VEX_INJECT_IR() \
436 do { \
437 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
438 "xchgq %%rdi,%%rdi\n\t" \
439 : : : "cc", "memory" \
440 ); \
441 } while (0)
442
njnf76d27a2009-05-28 01:53:07 +0000443#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +0000444
sewardjc913c8e2014-05-15 13:50:47 +0000445/* ------------------------- amd64-Win64 ------------------------- */
446
447#if defined(PLAT_amd64_win64) && !defined(__GNUC__)
448
449#error Unsupported compiler.
450
451#endif /* PLAT_amd64_win64 */
452
sewardjf5c1a7f2006-10-17 01:32:48 +0000453/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000454
sewardjf5c1a7f2006-10-17 01:32:48 +0000455#if defined(PLAT_ppc32_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000456
457typedef
458 struct {
sewardjc8858442006-01-20 15:17:20 +0000459 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000460 }
461 OrigFn;
462
sewardj0ec07f32006-01-12 12:32:32 +0000463#define __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj4decb262014-02-10 12:26:12 +0000464 "rlwinm 0,0,3,0,31 ; rlwinm 0,0,13,0,31\n\t" \
465 "rlwinm 0,0,29,0,31 ; rlwinm 0,0,19,0,31\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000466
bart575ce8e2011-05-15 07:04:03 +0000467#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
468 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000469 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000470 \
bart575ce8e2011-05-15 07:04:03 +0000471 __extension__ \
472 ({ unsigned int _zzq_args[6]; \
sewardj1c5bcb12006-12-08 21:29:46 +0000473 unsigned int _zzq_result; \
474 unsigned int* _zzq_ptr; \
sewardj0ec07f32006-01-12 12:32:32 +0000475 _zzq_args[0] = (unsigned int)(_zzq_request); \
476 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
477 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
478 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
479 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000480 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000481 _zzq_ptr = _zzq_args; \
sewardj1c5bcb12006-12-08 21:29:46 +0000482 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
483 "mr 4,%2\n\t" /*ptr*/ \
484 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj0ec07f32006-01-12 12:32:32 +0000485 /* %R3 = client_request ( %R4 ) */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000486 "or 1,1,1\n\t" \
487 "mr %0,3" /*result*/ \
488 : "=b" (_zzq_result) \
489 : "b" (_zzq_default), "b" (_zzq_ptr) \
490 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000491 _zzq_result; \
492 })
sewardj0ec07f32006-01-12 12:32:32 +0000493
sewardjd68ac3e2006-01-20 14:31:57 +0000494#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
495 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj1c5bcb12006-12-08 21:29:46 +0000496 unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000497 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
498 /* %R3 = guest_NRADDR */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000499 "or 2,2,2\n\t" \
500 "mr %0,3" \
501 : "=b" (__addr) \
sewardj0ec07f32006-01-12 12:32:32 +0000502 : \
sewardj1c5bcb12006-12-08 21:29:46 +0000503 : "cc", "memory", "r3" \
sewardj0ec07f32006-01-12 12:32:32 +0000504 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000505 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000506 }
507
508#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
509 __SPECIAL_INSTRUCTION_PREAMBLE \
510 /* branch-and-link-to-noredir *%R11 */ \
511 "or 3,3,3\n\t"
florian4d261bb2012-08-29 14:59:13 +0000512
513#define VALGRIND_VEX_INJECT_IR() \
514 do { \
515 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
516 "or 5,5,5\n\t" \
517 ); \
518 } while (0)
519
sewardjf5c1a7f2006-10-17 01:32:48 +0000520#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000521
sewardjf5c1a7f2006-10-17 01:32:48 +0000522/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000523
sewardjf5c1a7f2006-10-17 01:32:48 +0000524#if defined(PLAT_ppc64_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000525
526typedef
527 struct {
528 unsigned long long int nraddr; /* where's the code? */
529 unsigned long long int r2; /* what tocptr do we need? */
530 }
531 OrigFn;
532
sewardj1a85f4f2006-01-12 21:15:35 +0000533#define __SPECIAL_INSTRUCTION_PREAMBLE \
534 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
535 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
536
bart575ce8e2011-05-15 07:04:03 +0000537#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
538 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000539 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000540 \
bart575ce8e2011-05-15 07:04:03 +0000541 __extension__ \
542 ({ unsigned long long int _zzq_args[6]; \
sewardj8258a3a2011-10-05 07:39:07 +0000543 unsigned long long int _zzq_result; \
544 unsigned long long int* _zzq_ptr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000545 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
546 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
547 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
548 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
549 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000550 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000551 _zzq_ptr = _zzq_args; \
sewardj8258a3a2011-10-05 07:39:07 +0000552 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
553 "mr 4,%2\n\t" /*ptr*/ \
554 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj1a85f4f2006-01-12 21:15:35 +0000555 /* %R3 = client_request ( %R4 ) */ \
sewardj8258a3a2011-10-05 07:39:07 +0000556 "or 1,1,1\n\t" \
557 "mr %0,3" /*result*/ \
558 : "=b" (_zzq_result) \
559 : "b" (_zzq_default), "b" (_zzq_ptr) \
560 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000561 _zzq_result; \
562 })
sewardj1a85f4f2006-01-12 21:15:35 +0000563
sewardjd68ac3e2006-01-20 14:31:57 +0000564#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
565 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj8258a3a2011-10-05 07:39:07 +0000566 unsigned long long int __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000567 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
568 /* %R3 = guest_NRADDR */ \
sewardj8258a3a2011-10-05 07:39:07 +0000569 "or 2,2,2\n\t" \
570 "mr %0,3" \
571 : "=b" (__addr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000572 : \
sewardj8258a3a2011-10-05 07:39:07 +0000573 : "cc", "memory", "r3" \
sewardj1a85f4f2006-01-12 21:15:35 +0000574 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000575 _zzq_orig->nraddr = __addr; \
576 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
577 /* %R3 = guest_NRADDR_GPR2 */ \
sewardj8258a3a2011-10-05 07:39:07 +0000578 "or 4,4,4\n\t" \
579 "mr %0,3" \
580 : "=b" (__addr) \
sewardjd68ac3e2006-01-20 14:31:57 +0000581 : \
sewardj8258a3a2011-10-05 07:39:07 +0000582 : "cc", "memory", "r3" \
sewardjd68ac3e2006-01-20 14:31:57 +0000583 ); \
584 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000585 }
586
587#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
588 __SPECIAL_INSTRUCTION_PREAMBLE \
589 /* branch-and-link-to-noredir *%R11 */ \
590 "or 3,3,3\n\t"
591
florianbb913cd2012-08-28 16:50:39 +0000592#define VALGRIND_VEX_INJECT_IR() \
593 do { \
594 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
595 "or 5,5,5\n\t" \
596 ); \
597 } while (0)
598
sewardjf5c1a7f2006-10-17 01:32:48 +0000599#endif /* PLAT_ppc64_linux */
cerion85665ca2005-06-20 15:51:07 +0000600
sewardj59570ff2010-01-01 11:59:33 +0000601/* ------------------------- arm-linux ------------------------- */
602
603#if defined(PLAT_arm_linux)
604
605typedef
606 struct {
607 unsigned int nraddr; /* where's the code? */
608 }
609 OrigFn;
610
611#define __SPECIAL_INSTRUCTION_PREAMBLE \
612 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
613 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
614
bart575ce8e2011-05-15 07:04:03 +0000615#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
616 _zzq_default, _zzq_request, \
sewardj59570ff2010-01-01 11:59:33 +0000617 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
618 \
bart575ce8e2011-05-15 07:04:03 +0000619 __extension__ \
620 ({volatile unsigned int _zzq_args[6]; \
sewardj59570ff2010-01-01 11:59:33 +0000621 volatile unsigned int _zzq_result; \
622 _zzq_args[0] = (unsigned int)(_zzq_request); \
623 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
624 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
625 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
626 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
627 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
628 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
629 "mov r4, %2\n\t" /*ptr*/ \
630 __SPECIAL_INSTRUCTION_PREAMBLE \
631 /* R3 = client_request ( R4 ) */ \
632 "orr r10, r10, r10\n\t" \
633 "mov %0, r3" /*result*/ \
634 : "=r" (_zzq_result) \
635 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
636 : "cc","memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000637 _zzq_result; \
638 })
sewardj59570ff2010-01-01 11:59:33 +0000639
640#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
641 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
642 unsigned int __addr; \
643 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
644 /* R3 = guest_NRADDR */ \
645 "orr r11, r11, r11\n\t" \
646 "mov %0, r3" \
647 : "=r" (__addr) \
648 : \
649 : "cc", "memory", "r3" \
650 ); \
651 _zzq_orig->nraddr = __addr; \
652 }
653
654#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
655 __SPECIAL_INSTRUCTION_PREAMBLE \
656 /* branch-and-link-to-noredir *%R4 */ \
657 "orr r12, r12, r12\n\t"
658
florianbb913cd2012-08-28 16:50:39 +0000659#define VALGRIND_VEX_INJECT_IR() \
660 do { \
661 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
sewardjc379fec2012-09-03 21:51:02 +0000662 "orr r9, r9, r9\n\t" \
florianbb913cd2012-08-28 16:50:39 +0000663 : : : "cc", "memory" \
664 ); \
665 } while (0)
666
sewardj59570ff2010-01-01 11:59:33 +0000667#endif /* PLAT_arm_linux */
668
sewardjf0c12502014-01-12 12:54:00 +0000669/* ------------------------ arm64-linux ------------------------- */
670
671#if defined(PLAT_arm64_linux)
672
673typedef
674 struct {
675 unsigned long long int nraddr; /* where's the code? */
676 }
677 OrigFn;
678
679#define __SPECIAL_INSTRUCTION_PREAMBLE \
680 "ror x12, x12, #3 ; ror x12, x12, #13 \n\t" \
681 "ror x12, x12, #51 ; ror x12, x12, #61 \n\t"
682
683#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
684 _zzq_default, _zzq_request, \
685 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
686 \
687 __extension__ \
688 ({volatile unsigned long long int _zzq_args[6]; \
689 volatile unsigned long long int _zzq_result; \
690 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
691 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
692 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
693 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
694 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
695 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
696 __asm__ volatile("mov x3, %1\n\t" /*default*/ \
697 "mov x4, %2\n\t" /*ptr*/ \
698 __SPECIAL_INSTRUCTION_PREAMBLE \
699 /* X3 = client_request ( X4 ) */ \
700 "orr x10, x10, x10\n\t" \
701 "mov %0, x3" /*result*/ \
702 : "=r" (_zzq_result) \
703 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
704 : "cc","memory", "x3", "x4"); \
705 _zzq_result; \
706 })
707
708#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
709 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
710 unsigned long long int __addr; \
711 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
712 /* X3 = guest_NRADDR */ \
713 "orr x11, x11, x11\n\t" \
714 "mov %0, x3" \
715 : "=r" (__addr) \
716 : \
717 : "cc", "memory", "x3" \
718 ); \
719 _zzq_orig->nraddr = __addr; \
720 }
721
722#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
723 __SPECIAL_INSTRUCTION_PREAMBLE \
724 /* branch-and-link-to-noredir X8 */ \
725 "orr x12, x12, x12\n\t"
726
727#define VALGRIND_VEX_INJECT_IR() \
728 do { \
729 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
730 "orr x9, x9, x9\n\t" \
731 : : : "cc", "memory" \
732 ); \
733 } while (0)
734
735#endif /* PLAT_arm64_linux */
736
sewardjb5b87402011-03-07 16:05:35 +0000737/* ------------------------ s390x-linux ------------------------ */
738
739#if defined(PLAT_s390x_linux)
740
741typedef
742 struct {
743 unsigned long long int nraddr; /* where's the code? */
744 }
745 OrigFn;
746
747/* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific
748 * code. This detection is implemented in platform specific toIR.c
749 * (e.g. VEX/priv/guest_s390_decoder.c).
750 */
751#define __SPECIAL_INSTRUCTION_PREAMBLE \
752 "lr 15,15\n\t" \
753 "lr 1,1\n\t" \
754 "lr 2,2\n\t" \
755 "lr 3,3\n\t"
756
757#define __CLIENT_REQUEST_CODE "lr 2,2\n\t"
758#define __GET_NR_CONTEXT_CODE "lr 3,3\n\t"
759#define __CALL_NO_REDIR_CODE "lr 4,4\n\t"
florianbb913cd2012-08-28 16:50:39 +0000760#define __VEX_INJECT_IR_CODE "lr 5,5\n\t"
sewardjb5b87402011-03-07 16:05:35 +0000761
bart575ce8e2011-05-15 07:04:03 +0000762#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
763 _zzq_default, _zzq_request, \
sewardjb5b87402011-03-07 16:05:35 +0000764 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000765 __extension__ \
766 ({volatile unsigned long long int _zzq_args[6]; \
sewardjb5b87402011-03-07 16:05:35 +0000767 volatile unsigned long long int _zzq_result; \
768 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
769 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
770 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
771 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
772 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
773 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
774 __asm__ volatile(/* r2 = args */ \
775 "lgr 2,%1\n\t" \
776 /* r3 = default */ \
777 "lgr 3,%2\n\t" \
778 __SPECIAL_INSTRUCTION_PREAMBLE \
779 __CLIENT_REQUEST_CODE \
780 /* results = r3 */ \
781 "lgr %0, 3\n\t" \
782 : "=d" (_zzq_result) \
783 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
784 : "cc", "2", "3", "memory" \
785 ); \
bart575ce8e2011-05-15 07:04:03 +0000786 _zzq_result; \
787 })
sewardjb5b87402011-03-07 16:05:35 +0000788
789#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
790 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
791 volatile unsigned long long int __addr; \
792 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
793 __GET_NR_CONTEXT_CODE \
794 "lgr %0, 3\n\t" \
795 : "=a" (__addr) \
796 : \
797 : "cc", "3", "memory" \
798 ); \
799 _zzq_orig->nraddr = __addr; \
800 }
801
802#define VALGRIND_CALL_NOREDIR_R1 \
803 __SPECIAL_INSTRUCTION_PREAMBLE \
804 __CALL_NO_REDIR_CODE
805
florianbb913cd2012-08-28 16:50:39 +0000806#define VALGRIND_VEX_INJECT_IR() \
807 do { \
808 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
809 __VEX_INJECT_IR_CODE); \
810 } while (0)
811
sewardjb5b87402011-03-07 16:05:35 +0000812#endif /* PLAT_s390x_linux */
813
sewardj5db15402012-06-07 09:13:21 +0000814/* ------------------------- mips32-linux ---------------- */
815
816#if defined(PLAT_mips32_linux)
817
818typedef
819 struct {
820 unsigned int nraddr; /* where's the code? */
821 }
822 OrigFn;
823
824/* .word 0x342
825 * .word 0x742
826 * .word 0xC2
827 * .word 0x4C2*/
828#define __SPECIAL_INSTRUCTION_PREAMBLE \
829 "srl $0, $0, 13\n\t" \
830 "srl $0, $0, 29\n\t" \
831 "srl $0, $0, 3\n\t" \
832 "srl $0, $0, 19\n\t"
833
834#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
835 _zzq_default, _zzq_request, \
836 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
837 __extension__ \
838 ({ volatile unsigned int _zzq_args[6]; \
839 volatile unsigned int _zzq_result; \
840 _zzq_args[0] = (unsigned int)(_zzq_request); \
841 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
842 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
843 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
844 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
845 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
846 __asm__ volatile("move $11, %1\n\t" /*default*/ \
847 "move $12, %2\n\t" /*ptr*/ \
848 __SPECIAL_INSTRUCTION_PREAMBLE \
849 /* T3 = client_request ( T4 ) */ \
850 "or $13, $13, $13\n\t" \
851 "move %0, $11\n\t" /*result*/ \
852 : "=r" (_zzq_result) \
853 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
petarj4df0bfc2013-02-27 23:17:33 +0000854 : "$11", "$12"); \
sewardj5db15402012-06-07 09:13:21 +0000855 _zzq_result; \
856 })
857
858#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
859 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
860 volatile unsigned int __addr; \
861 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
862 /* %t9 = guest_NRADDR */ \
863 "or $14, $14, $14\n\t" \
864 "move %0, $11" /*result*/ \
865 : "=r" (__addr) \
866 : \
petarj4df0bfc2013-02-27 23:17:33 +0000867 : "$11" \
sewardj5db15402012-06-07 09:13:21 +0000868 ); \
869 _zzq_orig->nraddr = __addr; \
870 }
871
872#define VALGRIND_CALL_NOREDIR_T9 \
873 __SPECIAL_INSTRUCTION_PREAMBLE \
874 /* call-noredir *%t9 */ \
florianbb913cd2012-08-28 16:50:39 +0000875 "or $15, $15, $15\n\t"
876
877#define VALGRIND_VEX_INJECT_IR() \
878 do { \
879 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
880 "or $11, $11, $11\n\t" \
881 ); \
882 } while (0)
883
884
sewardj5db15402012-06-07 09:13:21 +0000885#endif /* PLAT_mips32_linux */
886
petarj4df0bfc2013-02-27 23:17:33 +0000887/* ------------------------- mips64-linux ---------------- */
888
889#if defined(PLAT_mips64_linux)
890
891typedef
892 struct {
893 unsigned long long nraddr; /* where's the code? */
894 }
895 OrigFn;
896
897/* dsll $0,$0, 3
898 * dsll $0,$0, 13
899 * dsll $0,$0, 29
900 * dsll $0,$0, 19*/
901#define __SPECIAL_INSTRUCTION_PREAMBLE \
902 "dsll $0,$0, 3 ; dsll $0,$0,13\n\t" \
903 "dsll $0,$0,29 ; dsll $0,$0,19\n\t"
904
905#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
906 _zzq_default, _zzq_request, \
907 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
908 __extension__ \
909 ({ volatile unsigned long long int _zzq_args[6]; \
910 volatile unsigned long long int _zzq_result; \
911 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
912 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
913 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
914 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
915 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
916 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
917 __asm__ volatile("move $11, %1\n\t" /*default*/ \
918 "move $12, %2\n\t" /*ptr*/ \
919 __SPECIAL_INSTRUCTION_PREAMBLE \
920 /* $11 = client_request ( $12 ) */ \
921 "or $13, $13, $13\n\t" \
922 "move %0, $11\n\t" /*result*/ \
923 : "=r" (_zzq_result) \
924 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
925 : "$11", "$12"); \
926 _zzq_result; \
927 })
928
929#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
930 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
931 volatile unsigned long long int __addr; \
932 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
933 /* $11 = guest_NRADDR */ \
934 "or $14, $14, $14\n\t" \
935 "move %0, $11" /*result*/ \
936 : "=r" (__addr) \
937 : \
938 : "$11"); \
939 _zzq_orig->nraddr = __addr; \
940 }
941
942#define VALGRIND_CALL_NOREDIR_T9 \
943 __SPECIAL_INSTRUCTION_PREAMBLE \
944 /* call-noredir $25 */ \
945 "or $15, $15, $15\n\t"
946
947#define VALGRIND_VEX_INJECT_IR() \
948 do { \
949 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
950 "or $11, $11, $11\n\t" \
951 ); \
952 } while (0)
953
954#endif /* PLAT_mips64_linux */
955
sewardjf5c1a7f2006-10-17 01:32:48 +0000956/* Insert assembly code for other platforms here... */
njn26aba4d2005-05-16 13:31:23 +0000957
sewardj37091fb2002-11-16 11:06:50 +0000958#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +0000959
nethercote69d9c462004-10-26 13:00:12 +0000960
njn30d76c62005-06-18 15:07:39 +0000961/* ------------------------------------------------------------------ */
sewardjf5c1a7f2006-10-17 01:32:48 +0000962/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
sewardj0ec07f32006-01-12 12:32:32 +0000963/* ugly. It's the least-worst tradeoff I can think of. */
964/* ------------------------------------------------------------------ */
965
966/* This section defines magic (a.k.a appalling-hack) macros for doing
967 guaranteed-no-redirection macros, so as to get from function
968 wrappers to the functions they are wrapping. The whole point is to
969 construct standard call sequences, but to do the call itself with a
970 special no-redirect call pseudo-instruction that the JIT
971 understands and handles specially. This section is long and
972 repetitious, and I can't see a way to make it shorter.
973
974 The naming scheme is as follows:
975
976 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
977
978 'W' stands for "word" and 'v' for "void". Hence there are
979 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
980 and for each, the possibility of returning a word-typed result, or
981 no result.
982*/
983
984/* Use these to write the name of your wrapper. NOTE: duplicates
sewardj85cf9002011-08-16 09:54:00 +0000985 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. NOTE also: inserts
986 the default behaviour equivalance class tag "0000" into the name.
987 See pub_tool_redir.h for details -- normally you don't need to
988 think about this, though. */
sewardj0ec07f32006-01-12 12:32:32 +0000989
njn5f5ef2a2009-05-11 08:01:09 +0000990/* Use an extra level of macroisation so as to ensure the soname/fnname
991 args are fully macro-expanded before pasting them together. */
992#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
993
sewardj0ec07f32006-01-12 12:32:32 +0000994#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +0000995 VG_CONCAT4(_vgw00000ZU_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000996
997#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +0000998 VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000999
sewardjd68ac3e2006-01-20 14:31:57 +00001000/* Use this macro from within a wrapper function to collect the
1001 context (address and possibly other info) of the original function.
1002 Once you have that you can then use it in one of the CALL_FN_
1003 macros. The type of the argument _lval is OrigFn. */
1004#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +00001005
sewardj573f8bc2012-06-05 07:12:15 +00001006/* Also provide end-user facilities for function replacement, rather
1007 than wrapping. A replacement function differs from a wrapper in
1008 that it has no way to get hold of the original function being
1009 called, and hence no way to call onwards to it. In a replacement
1010 function, VALGRIND_GET_ORIG_FN always returns zero. */
1011
1012#define I_REPLACE_SONAME_FNNAME_ZU(soname,fnname) \
1013 VG_CONCAT4(_vgr00000ZU_,soname,_,fnname)
1014
1015#define I_REPLACE_SONAME_FNNAME_ZZ(soname,fnname) \
1016 VG_CONCAT4(_vgr00000ZZ_,soname,_,fnname)
1017
sewardj0ec07f32006-01-12 12:32:32 +00001018/* Derivatives of the main macros below, for calling functions
1019 returning void. */
1020
1021#define CALL_FN_v_v(fnptr) \
1022 do { volatile unsigned long _junk; \
1023 CALL_FN_W_v(_junk,fnptr); } while (0)
1024
1025#define CALL_FN_v_W(fnptr, arg1) \
1026 do { volatile unsigned long _junk; \
1027 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
1028
1029#define CALL_FN_v_WW(fnptr, arg1,arg2) \
1030 do { volatile unsigned long _junk; \
1031 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
1032
sewardj5ce4b152006-03-11 12:57:41 +00001033#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
1034 do { volatile unsigned long _junk; \
1035 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
1036
njn2b5f0a92009-05-19 01:24:50 +00001037#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
1038 do { volatile unsigned long _junk; \
1039 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
1040
1041#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
1042 do { volatile unsigned long _junk; \
1043 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
1044
1045#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
1046 do { volatile unsigned long _junk; \
1047 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
1048
1049#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
1050 do { volatile unsigned long _junk; \
1051 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
1052
njnf76d27a2009-05-28 01:53:07 +00001053/* ------------------------- x86-{linux,darwin} ---------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001054
njnf76d27a2009-05-28 01:53:07 +00001055#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
sewardj0ec07f32006-01-12 12:32:32 +00001056
1057/* These regs are trashed by the hidden call. No need to mention eax
1058 as gcc can already see that, plus causes gcc to bomb. */
1059#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
1060
tom4118e0f2012-08-02 09:23:45 +00001061/* Macros to save and align the stack before making a function
1062 call and restore it afterwards as gcc may not keep the stack
1063 pointer aligned if it doesn't realise calls are being made
1064 to other functions. */
1065
1066#define VALGRIND_ALIGN_STACK \
1067 "movl %%esp,%%edi\n\t" \
1068 "andl $0xfffffff0,%%esp\n\t"
1069#define VALGRIND_RESTORE_STACK \
1070 "movl %%edi,%%esp\n\t"
1071
sewardj0ec07f32006-01-12 12:32:32 +00001072/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
1073 long) == 4. */
1074
sewardj66226cc2006-01-20 15:46:46 +00001075#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001076 do { \
sewardj66226cc2006-01-20 15:46:46 +00001077 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001078 volatile unsigned long _argvec[1]; \
1079 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001080 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001081 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001082 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001083 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1084 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001085 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001086 : /*out*/ "=a" (_res) \
1087 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001088 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001089 ); \
1090 lval = (__typeof__(lval)) _res; \
1091 } while (0)
1092
sewardj66226cc2006-01-20 15:46:46 +00001093#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001094 do { \
sewardj66226cc2006-01-20 15:46:46 +00001095 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001096 volatile unsigned long _argvec[2]; \
1097 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001098 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001099 _argvec[1] = (unsigned long)(arg1); \
1100 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001101 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001102 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001103 "pushl 4(%%eax)\n\t" \
1104 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1105 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001106 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001107 : /*out*/ "=a" (_res) \
1108 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001109 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001110 ); \
1111 lval = (__typeof__(lval)) _res; \
1112 } while (0)
1113
sewardj66226cc2006-01-20 15:46:46 +00001114#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001115 do { \
sewardj66226cc2006-01-20 15:46:46 +00001116 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001117 volatile unsigned long _argvec[3]; \
1118 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001119 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001120 _argvec[1] = (unsigned long)(arg1); \
1121 _argvec[2] = (unsigned long)(arg2); \
1122 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001123 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001124 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001125 "pushl 8(%%eax)\n\t" \
1126 "pushl 4(%%eax)\n\t" \
1127 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1128 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001129 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001130 : /*out*/ "=a" (_res) \
1131 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001132 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001133 ); \
1134 lval = (__typeof__(lval)) _res; \
1135 } while (0)
1136
sewardj9e8b07a2006-02-18 21:13:29 +00001137#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1138 do { \
1139 volatile OrigFn _orig = (orig); \
1140 volatile unsigned long _argvec[4]; \
1141 volatile unsigned long _res; \
1142 _argvec[0] = (unsigned long)_orig.nraddr; \
1143 _argvec[1] = (unsigned long)(arg1); \
1144 _argvec[2] = (unsigned long)(arg2); \
1145 _argvec[3] = (unsigned long)(arg3); \
1146 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001147 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001148 "subl $4, %%esp\n\t" \
sewardj9e8b07a2006-02-18 21:13:29 +00001149 "pushl 12(%%eax)\n\t" \
1150 "pushl 8(%%eax)\n\t" \
1151 "pushl 4(%%eax)\n\t" \
1152 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1153 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001154 VALGRIND_RESTORE_STACK \
sewardj9e8b07a2006-02-18 21:13:29 +00001155 : /*out*/ "=a" (_res) \
1156 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001157 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj9e8b07a2006-02-18 21:13:29 +00001158 ); \
1159 lval = (__typeof__(lval)) _res; \
1160 } while (0)
1161
sewardj66226cc2006-01-20 15:46:46 +00001162#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
sewardj0ec07f32006-01-12 12:32:32 +00001163 do { \
sewardj66226cc2006-01-20 15:46:46 +00001164 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001165 volatile unsigned long _argvec[5]; \
1166 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001167 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001168 _argvec[1] = (unsigned long)(arg1); \
1169 _argvec[2] = (unsigned long)(arg2); \
1170 _argvec[3] = (unsigned long)(arg3); \
1171 _argvec[4] = (unsigned long)(arg4); \
1172 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001173 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001174 "pushl 16(%%eax)\n\t" \
1175 "pushl 12(%%eax)\n\t" \
1176 "pushl 8(%%eax)\n\t" \
1177 "pushl 4(%%eax)\n\t" \
1178 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1179 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001180 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001181 : /*out*/ "=a" (_res) \
1182 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001183 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001184 ); \
1185 lval = (__typeof__(lval)) _res; \
1186 } while (0)
1187
sewardj66226cc2006-01-20 15:46:46 +00001188#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +00001189 do { \
sewardj66226cc2006-01-20 15:46:46 +00001190 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001191 volatile unsigned long _argvec[6]; \
1192 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001193 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001194 _argvec[1] = (unsigned long)(arg1); \
1195 _argvec[2] = (unsigned long)(arg2); \
1196 _argvec[3] = (unsigned long)(arg3); \
1197 _argvec[4] = (unsigned long)(arg4); \
1198 _argvec[5] = (unsigned long)(arg5); \
1199 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001200 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001201 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001202 "pushl 20(%%eax)\n\t" \
1203 "pushl 16(%%eax)\n\t" \
1204 "pushl 12(%%eax)\n\t" \
1205 "pushl 8(%%eax)\n\t" \
1206 "pushl 4(%%eax)\n\t" \
1207 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1208 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001209 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001210 : /*out*/ "=a" (_res) \
1211 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001212 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001213 ); \
1214 lval = (__typeof__(lval)) _res; \
1215 } while (0)
1216
sewardj66226cc2006-01-20 15:46:46 +00001217#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +00001218 do { \
sewardj66226cc2006-01-20 15:46:46 +00001219 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001220 volatile unsigned long _argvec[7]; \
1221 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001222 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001223 _argvec[1] = (unsigned long)(arg1); \
1224 _argvec[2] = (unsigned long)(arg2); \
1225 _argvec[3] = (unsigned long)(arg3); \
1226 _argvec[4] = (unsigned long)(arg4); \
1227 _argvec[5] = (unsigned long)(arg5); \
1228 _argvec[6] = (unsigned long)(arg6); \
1229 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001230 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001231 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001232 "pushl 24(%%eax)\n\t" \
1233 "pushl 20(%%eax)\n\t" \
1234 "pushl 16(%%eax)\n\t" \
1235 "pushl 12(%%eax)\n\t" \
1236 "pushl 8(%%eax)\n\t" \
1237 "pushl 4(%%eax)\n\t" \
1238 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1239 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001240 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001241 : /*out*/ "=a" (_res) \
1242 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001243 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001244 ); \
1245 lval = (__typeof__(lval)) _res; \
1246 } while (0)
1247
sewardj66226cc2006-01-20 15:46:46 +00001248#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1249 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +00001250 do { \
sewardj66226cc2006-01-20 15:46:46 +00001251 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001252 volatile unsigned long _argvec[8]; \
1253 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001254 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001255 _argvec[1] = (unsigned long)(arg1); \
1256 _argvec[2] = (unsigned long)(arg2); \
1257 _argvec[3] = (unsigned long)(arg3); \
1258 _argvec[4] = (unsigned long)(arg4); \
1259 _argvec[5] = (unsigned long)(arg5); \
1260 _argvec[6] = (unsigned long)(arg6); \
1261 _argvec[7] = (unsigned long)(arg7); \
1262 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001263 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001264 "subl $4, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001265 "pushl 28(%%eax)\n\t" \
1266 "pushl 24(%%eax)\n\t" \
1267 "pushl 20(%%eax)\n\t" \
1268 "pushl 16(%%eax)\n\t" \
1269 "pushl 12(%%eax)\n\t" \
1270 "pushl 8(%%eax)\n\t" \
1271 "pushl 4(%%eax)\n\t" \
1272 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1273 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001274 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001275 : /*out*/ "=a" (_res) \
1276 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001277 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001278 ); \
1279 lval = (__typeof__(lval)) _res; \
1280 } while (0)
1281
sewardj66226cc2006-01-20 15:46:46 +00001282#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1283 arg7,arg8) \
sewardj0ec07f32006-01-12 12:32:32 +00001284 do { \
sewardj66226cc2006-01-20 15:46:46 +00001285 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001286 volatile unsigned long _argvec[9]; \
1287 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001288 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001289 _argvec[1] = (unsigned long)(arg1); \
1290 _argvec[2] = (unsigned long)(arg2); \
1291 _argvec[3] = (unsigned long)(arg3); \
1292 _argvec[4] = (unsigned long)(arg4); \
1293 _argvec[5] = (unsigned long)(arg5); \
1294 _argvec[6] = (unsigned long)(arg6); \
1295 _argvec[7] = (unsigned long)(arg7); \
1296 _argvec[8] = (unsigned long)(arg8); \
1297 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001298 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001299 "pushl 32(%%eax)\n\t" \
1300 "pushl 28(%%eax)\n\t" \
1301 "pushl 24(%%eax)\n\t" \
1302 "pushl 20(%%eax)\n\t" \
1303 "pushl 16(%%eax)\n\t" \
1304 "pushl 12(%%eax)\n\t" \
1305 "pushl 8(%%eax)\n\t" \
1306 "pushl 4(%%eax)\n\t" \
1307 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1308 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001309 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001310 : /*out*/ "=a" (_res) \
1311 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001312 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001313 ); \
1314 lval = (__typeof__(lval)) _res; \
1315 } while (0)
1316
sewardj45fa5b02006-03-09 19:06:23 +00001317#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1318 arg7,arg8,arg9) \
1319 do { \
1320 volatile OrigFn _orig = (orig); \
1321 volatile unsigned long _argvec[10]; \
1322 volatile unsigned long _res; \
1323 _argvec[0] = (unsigned long)_orig.nraddr; \
1324 _argvec[1] = (unsigned long)(arg1); \
1325 _argvec[2] = (unsigned long)(arg2); \
1326 _argvec[3] = (unsigned long)(arg3); \
1327 _argvec[4] = (unsigned long)(arg4); \
1328 _argvec[5] = (unsigned long)(arg5); \
1329 _argvec[6] = (unsigned long)(arg6); \
1330 _argvec[7] = (unsigned long)(arg7); \
1331 _argvec[8] = (unsigned long)(arg8); \
1332 _argvec[9] = (unsigned long)(arg9); \
1333 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001334 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001335 "subl $12, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001336 "pushl 36(%%eax)\n\t" \
1337 "pushl 32(%%eax)\n\t" \
1338 "pushl 28(%%eax)\n\t" \
1339 "pushl 24(%%eax)\n\t" \
1340 "pushl 20(%%eax)\n\t" \
1341 "pushl 16(%%eax)\n\t" \
1342 "pushl 12(%%eax)\n\t" \
1343 "pushl 8(%%eax)\n\t" \
1344 "pushl 4(%%eax)\n\t" \
1345 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1346 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001347 VALGRIND_RESTORE_STACK \
sewardj45fa5b02006-03-09 19:06:23 +00001348 : /*out*/ "=a" (_res) \
1349 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001350 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj45fa5b02006-03-09 19:06:23 +00001351 ); \
1352 lval = (__typeof__(lval)) _res; \
1353 } while (0)
1354
1355#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1356 arg7,arg8,arg9,arg10) \
1357 do { \
1358 volatile OrigFn _orig = (orig); \
1359 volatile unsigned long _argvec[11]; \
1360 volatile unsigned long _res; \
1361 _argvec[0] = (unsigned long)_orig.nraddr; \
1362 _argvec[1] = (unsigned long)(arg1); \
1363 _argvec[2] = (unsigned long)(arg2); \
1364 _argvec[3] = (unsigned long)(arg3); \
1365 _argvec[4] = (unsigned long)(arg4); \
1366 _argvec[5] = (unsigned long)(arg5); \
1367 _argvec[6] = (unsigned long)(arg6); \
1368 _argvec[7] = (unsigned long)(arg7); \
1369 _argvec[8] = (unsigned long)(arg8); \
1370 _argvec[9] = (unsigned long)(arg9); \
1371 _argvec[10] = (unsigned long)(arg10); \
1372 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001373 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001374 "subl $8, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001375 "pushl 40(%%eax)\n\t" \
1376 "pushl 36(%%eax)\n\t" \
1377 "pushl 32(%%eax)\n\t" \
1378 "pushl 28(%%eax)\n\t" \
1379 "pushl 24(%%eax)\n\t" \
1380 "pushl 20(%%eax)\n\t" \
1381 "pushl 16(%%eax)\n\t" \
1382 "pushl 12(%%eax)\n\t" \
1383 "pushl 8(%%eax)\n\t" \
1384 "pushl 4(%%eax)\n\t" \
1385 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1386 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001387 VALGRIND_RESTORE_STACK \
sewardj45fa5b02006-03-09 19:06:23 +00001388 : /*out*/ "=a" (_res) \
1389 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001390 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj45fa5b02006-03-09 19:06:23 +00001391 ); \
1392 lval = (__typeof__(lval)) _res; \
1393 } while (0)
1394
sewardj5ce4b152006-03-11 12:57:41 +00001395#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1396 arg6,arg7,arg8,arg9,arg10, \
1397 arg11) \
1398 do { \
1399 volatile OrigFn _orig = (orig); \
1400 volatile unsigned long _argvec[12]; \
1401 volatile unsigned long _res; \
1402 _argvec[0] = (unsigned long)_orig.nraddr; \
1403 _argvec[1] = (unsigned long)(arg1); \
1404 _argvec[2] = (unsigned long)(arg2); \
1405 _argvec[3] = (unsigned long)(arg3); \
1406 _argvec[4] = (unsigned long)(arg4); \
1407 _argvec[5] = (unsigned long)(arg5); \
1408 _argvec[6] = (unsigned long)(arg6); \
1409 _argvec[7] = (unsigned long)(arg7); \
1410 _argvec[8] = (unsigned long)(arg8); \
1411 _argvec[9] = (unsigned long)(arg9); \
1412 _argvec[10] = (unsigned long)(arg10); \
1413 _argvec[11] = (unsigned long)(arg11); \
1414 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001415 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001416 "subl $4, %%esp\n\t" \
sewardj5ce4b152006-03-11 12:57:41 +00001417 "pushl 44(%%eax)\n\t" \
1418 "pushl 40(%%eax)\n\t" \
1419 "pushl 36(%%eax)\n\t" \
1420 "pushl 32(%%eax)\n\t" \
1421 "pushl 28(%%eax)\n\t" \
1422 "pushl 24(%%eax)\n\t" \
1423 "pushl 20(%%eax)\n\t" \
1424 "pushl 16(%%eax)\n\t" \
1425 "pushl 12(%%eax)\n\t" \
1426 "pushl 8(%%eax)\n\t" \
1427 "pushl 4(%%eax)\n\t" \
1428 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1429 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001430 VALGRIND_RESTORE_STACK \
sewardj5ce4b152006-03-11 12:57:41 +00001431 : /*out*/ "=a" (_res) \
1432 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001433 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj5ce4b152006-03-11 12:57:41 +00001434 ); \
1435 lval = (__typeof__(lval)) _res; \
1436 } while (0)
1437
sewardj66226cc2006-01-20 15:46:46 +00001438#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1439 arg6,arg7,arg8,arg9,arg10, \
1440 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +00001441 do { \
sewardj66226cc2006-01-20 15:46:46 +00001442 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001443 volatile unsigned long _argvec[13]; \
1444 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001445 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001446 _argvec[1] = (unsigned long)(arg1); \
1447 _argvec[2] = (unsigned long)(arg2); \
1448 _argvec[3] = (unsigned long)(arg3); \
1449 _argvec[4] = (unsigned long)(arg4); \
1450 _argvec[5] = (unsigned long)(arg5); \
1451 _argvec[6] = (unsigned long)(arg6); \
1452 _argvec[7] = (unsigned long)(arg7); \
1453 _argvec[8] = (unsigned long)(arg8); \
1454 _argvec[9] = (unsigned long)(arg9); \
1455 _argvec[10] = (unsigned long)(arg10); \
1456 _argvec[11] = (unsigned long)(arg11); \
1457 _argvec[12] = (unsigned long)(arg12); \
1458 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001459 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001460 "pushl 48(%%eax)\n\t" \
1461 "pushl 44(%%eax)\n\t" \
1462 "pushl 40(%%eax)\n\t" \
1463 "pushl 36(%%eax)\n\t" \
1464 "pushl 32(%%eax)\n\t" \
1465 "pushl 28(%%eax)\n\t" \
1466 "pushl 24(%%eax)\n\t" \
1467 "pushl 20(%%eax)\n\t" \
1468 "pushl 16(%%eax)\n\t" \
1469 "pushl 12(%%eax)\n\t" \
1470 "pushl 8(%%eax)\n\t" \
1471 "pushl 4(%%eax)\n\t" \
1472 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1473 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001474 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001475 : /*out*/ "=a" (_res) \
1476 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001477 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001478 ); \
1479 lval = (__typeof__(lval)) _res; \
1480 } while (0)
1481
njnf76d27a2009-05-28 01:53:07 +00001482#endif /* PLAT_x86_linux || PLAT_x86_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001483
njnf76d27a2009-05-28 01:53:07 +00001484/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001485
njnf76d27a2009-05-28 01:53:07 +00001486#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardj0ec07f32006-01-12 12:32:32 +00001487
1488/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1489
1490/* These regs are trashed by the hidden call. */
1491#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1492 "rdi", "r8", "r9", "r10", "r11"
1493
sewardjdfa55cf2010-10-06 22:07:06 +00001494/* This is all pretty complex. It's so as to make stack unwinding
1495 work reliably. See bug 243270. The basic problem is the sub and
1496 add of 128 of %rsp in all of the following macros. If gcc believes
1497 the CFA is in %rsp, then unwinding may fail, because what's at the
1498 CFA is not what gcc "expected" when it constructs the CFIs for the
1499 places where the macros are instantiated.
1500
1501 But we can't just add a CFI annotation to increase the CFA offset
1502 by 128, to match the sub of 128 from %rsp, because we don't know
1503 whether gcc has chosen %rsp as the CFA at that point, or whether it
1504 has chosen some other register (eg, %rbp). In the latter case,
1505 adding a CFI annotation to change the CFA offset is simply wrong.
1506
1507 So the solution is to get hold of the CFA using
sewardj8d1dc152010-10-08 17:43:26 +00001508 __builtin_dwarf_cfa(), put it in a known register, and add a
sewardjdfa55cf2010-10-06 22:07:06 +00001509 CFI annotation to say what the register is. We choose %rbp for
1510 this (perhaps perversely), because:
1511
1512 (1) %rbp is already subject to unwinding. If a new register was
1513 chosen then the unwinder would have to unwind it in all stack
1514 traces, which is expensive, and
1515
1516 (2) %rbp is already subject to precise exception updates in the
1517 JIT. If a new register was chosen, we'd have to have precise
1518 exceptions for it too, which reduces performance of the
1519 generated code.
1520
1521 However .. one extra complication. We can't just whack the result
sewardj8d1dc152010-10-08 17:43:26 +00001522 of __builtin_dwarf_cfa() into %rbp and then add %rbp to the
sewardjdfa55cf2010-10-06 22:07:06 +00001523 list of trashed registers at the end of the inline assembly
1524 fragments; gcc won't allow %rbp to appear in that list. Hence
1525 instead we need to stash %rbp in %r15 for the duration of the asm,
1526 and say that %r15 is trashed instead. gcc seems happy to go with
1527 that.
1528
1529 Oh .. and this all needs to be conditionalised so that it is
1530 unchanged from before this commit, when compiled with older gccs
sewardj8d1dc152010-10-08 17:43:26 +00001531 that don't support __builtin_dwarf_cfa. Furthermore, since
1532 this header file is freestanding, it has to be independent of
1533 config.h, and so the following conditionalisation cannot depend on
1534 configure time checks.
1535
1536 Although it's not clear from
1537 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)',
1538 this expression excludes Darwin.
1539 .cfi directives in Darwin assembly appear to be completely
1540 different and I haven't investigated how they work.
1541
1542 For even more entertainment value, note we have to use the
1543 completely undocumented __builtin_dwarf_cfa(), which appears to
1544 really compute the CFA, whereas __builtin_frame_address(0) claims
1545 to but actually doesn't. See
1546 https://bugs.kde.org/show_bug.cgi?id=243270#c47
sewardjdfa55cf2010-10-06 22:07:06 +00001547*/
sewardj8d1dc152010-10-08 17:43:26 +00001548#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
sewardjdfa55cf2010-10-06 22:07:06 +00001549# define __FRAME_POINTER \
sewardj8d1dc152010-10-08 17:43:26 +00001550 ,"r"(__builtin_dwarf_cfa())
sewardjdfa55cf2010-10-06 22:07:06 +00001551# define VALGRIND_CFI_PROLOGUE \
sewardjdfa55cf2010-10-06 22:07:06 +00001552 "movq %%rbp, %%r15\n\t" \
sewardj8d1dc152010-10-08 17:43:26 +00001553 "movq %2, %%rbp\n\t" \
1554 ".cfi_remember_state\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001555 ".cfi_def_cfa rbp, 0\n\t"
1556# define VALGRIND_CFI_EPILOGUE \
1557 "movq %%r15, %%rbp\n\t" \
1558 ".cfi_restore_state\n\t"
1559#else
1560# define __FRAME_POINTER
1561# define VALGRIND_CFI_PROLOGUE
1562# define VALGRIND_CFI_EPILOGUE
1563#endif
1564
tom4118e0f2012-08-02 09:23:45 +00001565/* Macros to save and align the stack before making a function
1566 call and restore it afterwards as gcc may not keep the stack
1567 pointer aligned if it doesn't realise calls are being made
1568 to other functions. */
1569
1570#define VALGRIND_ALIGN_STACK \
1571 "movq %%rsp,%%r14\n\t" \
1572 "andq $0xfffffffffffffff0,%%rsp\n\t"
1573#define VALGRIND_RESTORE_STACK \
1574 "movq %%r14,%%rsp\n\t"
sewardjdfa55cf2010-10-06 22:07:06 +00001575
sewardj0ec07f32006-01-12 12:32:32 +00001576/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1577 long) == 8. */
1578
sewardja07c2e12007-11-09 23:09:50 +00001579/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1580 macros. In order not to trash the stack redzone, we need to drop
1581 %rsp by 128 before the hidden call, and restore afterwards. The
1582 nastyness is that it is only by luck that the stack still appears
1583 to be unwindable during the hidden call - since then the behaviour
1584 of any routine using this macro does not match what the CFI data
1585 says. Sigh.
1586
1587 Why is this important? Imagine that a wrapper has a stack
1588 allocated local, and passes to the hidden call, a pointer to it.
1589 Because gcc does not know about the hidden call, it may allocate
1590 that local in the redzone. Unfortunately the hidden call may then
1591 trash it before it comes to use it. So we must step clear of the
1592 redzone, for the duration of the hidden call, to make it safe.
1593
1594 Probably the same problem afflicts the other redzone-style ABIs too
sewardj6e9de462011-06-28 07:25:29 +00001595 (ppc64-linux); but for those, the stack is
sewardja07c2e12007-11-09 23:09:50 +00001596 self describing (none of this CFI nonsense) so at least messing
1597 with the stack pointer doesn't give a danger of non-unwindable
1598 stack. */
1599
tom4118e0f2012-08-02 09:23:45 +00001600#define CALL_FN_W_v(lval, orig) \
1601 do { \
1602 volatile OrigFn _orig = (orig); \
1603 volatile unsigned long _argvec[1]; \
1604 volatile unsigned long _res; \
1605 _argvec[0] = (unsigned long)_orig.nraddr; \
1606 __asm__ volatile( \
1607 VALGRIND_CFI_PROLOGUE \
1608 VALGRIND_ALIGN_STACK \
1609 "subq $128,%%rsp\n\t" \
1610 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1611 VALGRIND_CALL_NOREDIR_RAX \
1612 VALGRIND_RESTORE_STACK \
1613 VALGRIND_CFI_EPILOGUE \
1614 : /*out*/ "=a" (_res) \
1615 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1616 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1617 ); \
1618 lval = (__typeof__(lval)) _res; \
sewardj0ec07f32006-01-12 12:32:32 +00001619 } while (0)
1620
tom4118e0f2012-08-02 09:23:45 +00001621#define CALL_FN_W_W(lval, orig, arg1) \
1622 do { \
1623 volatile OrigFn _orig = (orig); \
1624 volatile unsigned long _argvec[2]; \
1625 volatile unsigned long _res; \
1626 _argvec[0] = (unsigned long)_orig.nraddr; \
1627 _argvec[1] = (unsigned long)(arg1); \
1628 __asm__ volatile( \
1629 VALGRIND_CFI_PROLOGUE \
1630 VALGRIND_ALIGN_STACK \
1631 "subq $128,%%rsp\n\t" \
1632 "movq 8(%%rax), %%rdi\n\t" \
1633 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1634 VALGRIND_CALL_NOREDIR_RAX \
1635 VALGRIND_RESTORE_STACK \
1636 VALGRIND_CFI_EPILOGUE \
1637 : /*out*/ "=a" (_res) \
1638 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1639 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1640 ); \
1641 lval = (__typeof__(lval)) _res; \
sewardj0ec07f32006-01-12 12:32:32 +00001642 } while (0)
1643
tom4118e0f2012-08-02 09:23:45 +00001644#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1645 do { \
1646 volatile OrigFn _orig = (orig); \
1647 volatile unsigned long _argvec[3]; \
1648 volatile unsigned long _res; \
1649 _argvec[0] = (unsigned long)_orig.nraddr; \
1650 _argvec[1] = (unsigned long)(arg1); \
1651 _argvec[2] = (unsigned long)(arg2); \
1652 __asm__ volatile( \
1653 VALGRIND_CFI_PROLOGUE \
1654 VALGRIND_ALIGN_STACK \
1655 "subq $128,%%rsp\n\t" \
1656 "movq 16(%%rax), %%rsi\n\t" \
1657 "movq 8(%%rax), %%rdi\n\t" \
1658 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1659 VALGRIND_CALL_NOREDIR_RAX \
1660 VALGRIND_RESTORE_STACK \
1661 VALGRIND_CFI_EPILOGUE \
1662 : /*out*/ "=a" (_res) \
1663 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1664 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1665 ); \
1666 lval = (__typeof__(lval)) _res; \
sewardj0ec07f32006-01-12 12:32:32 +00001667 } while (0)
1668
tom4118e0f2012-08-02 09:23:45 +00001669#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1670 do { \
1671 volatile OrigFn _orig = (orig); \
1672 volatile unsigned long _argvec[4]; \
1673 volatile unsigned long _res; \
1674 _argvec[0] = (unsigned long)_orig.nraddr; \
1675 _argvec[1] = (unsigned long)(arg1); \
1676 _argvec[2] = (unsigned long)(arg2); \
1677 _argvec[3] = (unsigned long)(arg3); \
1678 __asm__ volatile( \
1679 VALGRIND_CFI_PROLOGUE \
1680 VALGRIND_ALIGN_STACK \
1681 "subq $128,%%rsp\n\t" \
1682 "movq 24(%%rax), %%rdx\n\t" \
1683 "movq 16(%%rax), %%rsi\n\t" \
1684 "movq 8(%%rax), %%rdi\n\t" \
1685 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1686 VALGRIND_CALL_NOREDIR_RAX \
1687 VALGRIND_RESTORE_STACK \
1688 VALGRIND_CFI_EPILOGUE \
1689 : /*out*/ "=a" (_res) \
1690 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1691 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1692 ); \
1693 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001694 } while (0)
1695
tom4118e0f2012-08-02 09:23:45 +00001696#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1697 do { \
1698 volatile OrigFn _orig = (orig); \
1699 volatile unsigned long _argvec[5]; \
1700 volatile unsigned long _res; \
1701 _argvec[0] = (unsigned long)_orig.nraddr; \
1702 _argvec[1] = (unsigned long)(arg1); \
1703 _argvec[2] = (unsigned long)(arg2); \
1704 _argvec[3] = (unsigned long)(arg3); \
1705 _argvec[4] = (unsigned long)(arg4); \
1706 __asm__ volatile( \
1707 VALGRIND_CFI_PROLOGUE \
1708 VALGRIND_ALIGN_STACK \
1709 "subq $128,%%rsp\n\t" \
1710 "movq 32(%%rax), %%rcx\n\t" \
1711 "movq 24(%%rax), %%rdx\n\t" \
1712 "movq 16(%%rax), %%rsi\n\t" \
1713 "movq 8(%%rax), %%rdi\n\t" \
1714 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1715 VALGRIND_CALL_NOREDIR_RAX \
1716 VALGRIND_RESTORE_STACK \
1717 VALGRIND_CFI_EPILOGUE \
1718 : /*out*/ "=a" (_res) \
1719 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1720 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1721 ); \
1722 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001723 } while (0)
1724
tom4118e0f2012-08-02 09:23:45 +00001725#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1726 do { \
1727 volatile OrigFn _orig = (orig); \
1728 volatile unsigned long _argvec[6]; \
1729 volatile unsigned long _res; \
1730 _argvec[0] = (unsigned long)_orig.nraddr; \
1731 _argvec[1] = (unsigned long)(arg1); \
1732 _argvec[2] = (unsigned long)(arg2); \
1733 _argvec[3] = (unsigned long)(arg3); \
1734 _argvec[4] = (unsigned long)(arg4); \
1735 _argvec[5] = (unsigned long)(arg5); \
1736 __asm__ volatile( \
1737 VALGRIND_CFI_PROLOGUE \
1738 VALGRIND_ALIGN_STACK \
1739 "subq $128,%%rsp\n\t" \
1740 "movq 40(%%rax), %%r8\n\t" \
1741 "movq 32(%%rax), %%rcx\n\t" \
1742 "movq 24(%%rax), %%rdx\n\t" \
1743 "movq 16(%%rax), %%rsi\n\t" \
1744 "movq 8(%%rax), %%rdi\n\t" \
1745 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1746 VALGRIND_CALL_NOREDIR_RAX \
1747 VALGRIND_RESTORE_STACK \
1748 VALGRIND_CFI_EPILOGUE \
1749 : /*out*/ "=a" (_res) \
1750 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1751 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1752 ); \
1753 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001754 } while (0)
1755
tom4118e0f2012-08-02 09:23:45 +00001756#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1757 do { \
1758 volatile OrigFn _orig = (orig); \
1759 volatile unsigned long _argvec[7]; \
1760 volatile unsigned long _res; \
1761 _argvec[0] = (unsigned long)_orig.nraddr; \
1762 _argvec[1] = (unsigned long)(arg1); \
1763 _argvec[2] = (unsigned long)(arg2); \
1764 _argvec[3] = (unsigned long)(arg3); \
1765 _argvec[4] = (unsigned long)(arg4); \
1766 _argvec[5] = (unsigned long)(arg5); \
1767 _argvec[6] = (unsigned long)(arg6); \
1768 __asm__ volatile( \
1769 VALGRIND_CFI_PROLOGUE \
1770 VALGRIND_ALIGN_STACK \
1771 "subq $128,%%rsp\n\t" \
1772 "movq 48(%%rax), %%r9\n\t" \
1773 "movq 40(%%rax), %%r8\n\t" \
1774 "movq 32(%%rax), %%rcx\n\t" \
1775 "movq 24(%%rax), %%rdx\n\t" \
1776 "movq 16(%%rax), %%rsi\n\t" \
1777 "movq 8(%%rax), %%rdi\n\t" \
1778 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1779 VALGRIND_CALL_NOREDIR_RAX \
1780 VALGRIND_RESTORE_STACK \
1781 VALGRIND_CFI_EPILOGUE \
1782 : /*out*/ "=a" (_res) \
1783 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1784 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1785 ); \
1786 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001787 } while (0)
1788
tom4118e0f2012-08-02 09:23:45 +00001789#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1790 arg7) \
1791 do { \
1792 volatile OrigFn _orig = (orig); \
1793 volatile unsigned long _argvec[8]; \
1794 volatile unsigned long _res; \
1795 _argvec[0] = (unsigned long)_orig.nraddr; \
1796 _argvec[1] = (unsigned long)(arg1); \
1797 _argvec[2] = (unsigned long)(arg2); \
1798 _argvec[3] = (unsigned long)(arg3); \
1799 _argvec[4] = (unsigned long)(arg4); \
1800 _argvec[5] = (unsigned long)(arg5); \
1801 _argvec[6] = (unsigned long)(arg6); \
1802 _argvec[7] = (unsigned long)(arg7); \
1803 __asm__ volatile( \
1804 VALGRIND_CFI_PROLOGUE \
1805 VALGRIND_ALIGN_STACK \
1806 "subq $136,%%rsp\n\t" \
1807 "pushq 56(%%rax)\n\t" \
1808 "movq 48(%%rax), %%r9\n\t" \
1809 "movq 40(%%rax), %%r8\n\t" \
1810 "movq 32(%%rax), %%rcx\n\t" \
1811 "movq 24(%%rax), %%rdx\n\t" \
1812 "movq 16(%%rax), %%rsi\n\t" \
1813 "movq 8(%%rax), %%rdi\n\t" \
1814 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1815 VALGRIND_CALL_NOREDIR_RAX \
1816 VALGRIND_RESTORE_STACK \
1817 VALGRIND_CFI_EPILOGUE \
1818 : /*out*/ "=a" (_res) \
1819 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1820 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1821 ); \
1822 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001823 } while (0)
1824
tom4118e0f2012-08-02 09:23:45 +00001825#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1826 arg7,arg8) \
1827 do { \
1828 volatile OrigFn _orig = (orig); \
1829 volatile unsigned long _argvec[9]; \
1830 volatile unsigned long _res; \
1831 _argvec[0] = (unsigned long)_orig.nraddr; \
1832 _argvec[1] = (unsigned long)(arg1); \
1833 _argvec[2] = (unsigned long)(arg2); \
1834 _argvec[3] = (unsigned long)(arg3); \
1835 _argvec[4] = (unsigned long)(arg4); \
1836 _argvec[5] = (unsigned long)(arg5); \
1837 _argvec[6] = (unsigned long)(arg6); \
1838 _argvec[7] = (unsigned long)(arg7); \
1839 _argvec[8] = (unsigned long)(arg8); \
1840 __asm__ volatile( \
1841 VALGRIND_CFI_PROLOGUE \
1842 VALGRIND_ALIGN_STACK \
1843 "subq $128,%%rsp\n\t" \
1844 "pushq 64(%%rax)\n\t" \
1845 "pushq 56(%%rax)\n\t" \
1846 "movq 48(%%rax), %%r9\n\t" \
1847 "movq 40(%%rax), %%r8\n\t" \
1848 "movq 32(%%rax), %%rcx\n\t" \
1849 "movq 24(%%rax), %%rdx\n\t" \
1850 "movq 16(%%rax), %%rsi\n\t" \
1851 "movq 8(%%rax), %%rdi\n\t" \
1852 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1853 VALGRIND_CALL_NOREDIR_RAX \
1854 VALGRIND_RESTORE_STACK \
1855 VALGRIND_CFI_EPILOGUE \
1856 : /*out*/ "=a" (_res) \
1857 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1858 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1859 ); \
1860 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001861 } while (0)
1862
tom4118e0f2012-08-02 09:23:45 +00001863#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1864 arg7,arg8,arg9) \
1865 do { \
1866 volatile OrigFn _orig = (orig); \
1867 volatile unsigned long _argvec[10]; \
1868 volatile unsigned long _res; \
1869 _argvec[0] = (unsigned long)_orig.nraddr; \
1870 _argvec[1] = (unsigned long)(arg1); \
1871 _argvec[2] = (unsigned long)(arg2); \
1872 _argvec[3] = (unsigned long)(arg3); \
1873 _argvec[4] = (unsigned long)(arg4); \
1874 _argvec[5] = (unsigned long)(arg5); \
1875 _argvec[6] = (unsigned long)(arg6); \
1876 _argvec[7] = (unsigned long)(arg7); \
1877 _argvec[8] = (unsigned long)(arg8); \
1878 _argvec[9] = (unsigned long)(arg9); \
1879 __asm__ volatile( \
1880 VALGRIND_CFI_PROLOGUE \
1881 VALGRIND_ALIGN_STACK \
1882 "subq $136,%%rsp\n\t" \
1883 "pushq 72(%%rax)\n\t" \
1884 "pushq 64(%%rax)\n\t" \
1885 "pushq 56(%%rax)\n\t" \
1886 "movq 48(%%rax), %%r9\n\t" \
1887 "movq 40(%%rax), %%r8\n\t" \
1888 "movq 32(%%rax), %%rcx\n\t" \
1889 "movq 24(%%rax), %%rdx\n\t" \
1890 "movq 16(%%rax), %%rsi\n\t" \
1891 "movq 8(%%rax), %%rdi\n\t" \
1892 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1893 VALGRIND_CALL_NOREDIR_RAX \
1894 VALGRIND_RESTORE_STACK \
1895 VALGRIND_CFI_EPILOGUE \
1896 : /*out*/ "=a" (_res) \
1897 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1898 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1899 ); \
1900 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001901 } while (0)
1902
tom4118e0f2012-08-02 09:23:45 +00001903#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1904 arg7,arg8,arg9,arg10) \
1905 do { \
1906 volatile OrigFn _orig = (orig); \
1907 volatile unsigned long _argvec[11]; \
1908 volatile unsigned long _res; \
1909 _argvec[0] = (unsigned long)_orig.nraddr; \
1910 _argvec[1] = (unsigned long)(arg1); \
1911 _argvec[2] = (unsigned long)(arg2); \
1912 _argvec[3] = (unsigned long)(arg3); \
1913 _argvec[4] = (unsigned long)(arg4); \
1914 _argvec[5] = (unsigned long)(arg5); \
1915 _argvec[6] = (unsigned long)(arg6); \
1916 _argvec[7] = (unsigned long)(arg7); \
1917 _argvec[8] = (unsigned long)(arg8); \
1918 _argvec[9] = (unsigned long)(arg9); \
1919 _argvec[10] = (unsigned long)(arg10); \
1920 __asm__ volatile( \
1921 VALGRIND_CFI_PROLOGUE \
1922 VALGRIND_ALIGN_STACK \
1923 "subq $128,%%rsp\n\t" \
1924 "pushq 80(%%rax)\n\t" \
1925 "pushq 72(%%rax)\n\t" \
1926 "pushq 64(%%rax)\n\t" \
1927 "pushq 56(%%rax)\n\t" \
1928 "movq 48(%%rax), %%r9\n\t" \
1929 "movq 40(%%rax), %%r8\n\t" \
1930 "movq 32(%%rax), %%rcx\n\t" \
1931 "movq 24(%%rax), %%rdx\n\t" \
1932 "movq 16(%%rax), %%rsi\n\t" \
1933 "movq 8(%%rax), %%rdi\n\t" \
1934 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1935 VALGRIND_CALL_NOREDIR_RAX \
1936 VALGRIND_RESTORE_STACK \
1937 VALGRIND_CFI_EPILOGUE \
1938 : /*out*/ "=a" (_res) \
1939 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1940 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1941 ); \
1942 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001943 } while (0)
1944
tom4118e0f2012-08-02 09:23:45 +00001945#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1946 arg7,arg8,arg9,arg10,arg11) \
1947 do { \
1948 volatile OrigFn _orig = (orig); \
1949 volatile unsigned long _argvec[12]; \
1950 volatile unsigned long _res; \
1951 _argvec[0] = (unsigned long)_orig.nraddr; \
1952 _argvec[1] = (unsigned long)(arg1); \
1953 _argvec[2] = (unsigned long)(arg2); \
1954 _argvec[3] = (unsigned long)(arg3); \
1955 _argvec[4] = (unsigned long)(arg4); \
1956 _argvec[5] = (unsigned long)(arg5); \
1957 _argvec[6] = (unsigned long)(arg6); \
1958 _argvec[7] = (unsigned long)(arg7); \
1959 _argvec[8] = (unsigned long)(arg8); \
1960 _argvec[9] = (unsigned long)(arg9); \
1961 _argvec[10] = (unsigned long)(arg10); \
1962 _argvec[11] = (unsigned long)(arg11); \
1963 __asm__ volatile( \
1964 VALGRIND_CFI_PROLOGUE \
1965 VALGRIND_ALIGN_STACK \
1966 "subq $136,%%rsp\n\t" \
1967 "pushq 88(%%rax)\n\t" \
1968 "pushq 80(%%rax)\n\t" \
1969 "pushq 72(%%rax)\n\t" \
1970 "pushq 64(%%rax)\n\t" \
1971 "pushq 56(%%rax)\n\t" \
1972 "movq 48(%%rax), %%r9\n\t" \
1973 "movq 40(%%rax), %%r8\n\t" \
1974 "movq 32(%%rax), %%rcx\n\t" \
1975 "movq 24(%%rax), %%rdx\n\t" \
1976 "movq 16(%%rax), %%rsi\n\t" \
1977 "movq 8(%%rax), %%rdi\n\t" \
1978 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1979 VALGRIND_CALL_NOREDIR_RAX \
1980 VALGRIND_RESTORE_STACK \
1981 VALGRIND_CFI_EPILOGUE \
1982 : /*out*/ "=a" (_res) \
1983 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1984 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1985 ); \
1986 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001987 } while (0)
1988
tom4118e0f2012-08-02 09:23:45 +00001989#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1990 arg7,arg8,arg9,arg10,arg11,arg12) \
1991 do { \
1992 volatile OrigFn _orig = (orig); \
1993 volatile unsigned long _argvec[13]; \
1994 volatile unsigned long _res; \
1995 _argvec[0] = (unsigned long)_orig.nraddr; \
1996 _argvec[1] = (unsigned long)(arg1); \
1997 _argvec[2] = (unsigned long)(arg2); \
1998 _argvec[3] = (unsigned long)(arg3); \
1999 _argvec[4] = (unsigned long)(arg4); \
2000 _argvec[5] = (unsigned long)(arg5); \
2001 _argvec[6] = (unsigned long)(arg6); \
2002 _argvec[7] = (unsigned long)(arg7); \
2003 _argvec[8] = (unsigned long)(arg8); \
2004 _argvec[9] = (unsigned long)(arg9); \
2005 _argvec[10] = (unsigned long)(arg10); \
2006 _argvec[11] = (unsigned long)(arg11); \
2007 _argvec[12] = (unsigned long)(arg12); \
2008 __asm__ volatile( \
2009 VALGRIND_CFI_PROLOGUE \
2010 VALGRIND_ALIGN_STACK \
2011 "subq $128,%%rsp\n\t" \
2012 "pushq 96(%%rax)\n\t" \
2013 "pushq 88(%%rax)\n\t" \
2014 "pushq 80(%%rax)\n\t" \
2015 "pushq 72(%%rax)\n\t" \
2016 "pushq 64(%%rax)\n\t" \
2017 "pushq 56(%%rax)\n\t" \
2018 "movq 48(%%rax), %%r9\n\t" \
2019 "movq 40(%%rax), %%r8\n\t" \
2020 "movq 32(%%rax), %%rcx\n\t" \
2021 "movq 24(%%rax), %%rdx\n\t" \
2022 "movq 16(%%rax), %%rsi\n\t" \
2023 "movq 8(%%rax), %%rdi\n\t" \
2024 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
2025 VALGRIND_CALL_NOREDIR_RAX \
2026 VALGRIND_RESTORE_STACK \
2027 VALGRIND_CFI_EPILOGUE \
2028 : /*out*/ "=a" (_res) \
2029 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
2030 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2031 ); \
2032 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00002033 } while (0)
2034
njnf76d27a2009-05-28 01:53:07 +00002035#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00002036
sewardjf5c1a7f2006-10-17 01:32:48 +00002037/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002038
sewardjf5c1a7f2006-10-17 01:32:48 +00002039#if defined(PLAT_ppc32_linux)
sewardj0ec07f32006-01-12 12:32:32 +00002040
sewardjead61df2006-03-12 13:39:15 +00002041/* This is useful for finding out about the on-stack stuff:
2042
2043 extern int f9 ( int,int,int,int,int,int,int,int,int );
2044 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
2045 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
2046 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
2047
2048 int g9 ( void ) {
2049 return f9(11,22,33,44,55,66,77,88,99);
2050 }
2051 int g10 ( void ) {
2052 return f10(11,22,33,44,55,66,77,88,99,110);
2053 }
2054 int g11 ( void ) {
2055 return f11(11,22,33,44,55,66,77,88,99,110,121);
2056 }
2057 int g12 ( void ) {
2058 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
2059 }
2060*/
2061
sewardj0ec07f32006-01-12 12:32:32 +00002062/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2063
2064/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00002065#define __CALLER_SAVED_REGS \
2066 "lr", "ctr", "xer", \
2067 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2068 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2069 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00002070
tom4118e0f2012-08-02 09:23:45 +00002071/* Macros to save and align the stack before making a function
2072 call and restore it afterwards as gcc may not keep the stack
2073 pointer aligned if it doesn't realise calls are being made
2074 to other functions. */
2075
2076#define VALGRIND_ALIGN_STACK \
2077 "mr 28,1\n\t" \
2078 "rlwinm 1,1,0,0,27\n\t"
2079#define VALGRIND_RESTORE_STACK \
2080 "mr 1,28\n\t"
2081
sewardjead61df2006-03-12 13:39:15 +00002082/* These CALL_FN_ macros assume that on ppc32-linux,
2083 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00002084
sewardj38de0992006-01-20 16:46:34 +00002085#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00002086 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002087 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00002088 volatile unsigned long _argvec[1]; \
2089 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002090 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00002091 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002092 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002093 "mr 11,%1\n\t" \
2094 "lwz 11,0(11)\n\t" /* target->r11 */ \
2095 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002096 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002097 "mr %0,3" \
2098 : /*out*/ "=r" (_res) \
2099 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002100 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj0ec07f32006-01-12 12:32:32 +00002101 ); \
2102 lval = (__typeof__(lval)) _res; \
2103 } while (0)
2104
sewardj38de0992006-01-20 16:46:34 +00002105#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00002106 do { \
sewardj38de0992006-01-20 16:46:34 +00002107 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00002108 volatile unsigned long _argvec[2]; \
2109 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00002110 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00002111 _argvec[1] = (unsigned long)arg1; \
2112 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002113 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002114 "mr 11,%1\n\t" \
2115 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2116 "lwz 11,0(11)\n\t" /* target->r11 */ \
2117 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002118 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002119 "mr %0,3" \
2120 : /*out*/ "=r" (_res) \
2121 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002122 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj0ec07f32006-01-12 12:32:32 +00002123 ); \
2124 lval = (__typeof__(lval)) _res; \
2125 } while (0)
2126
sewardj38de0992006-01-20 16:46:34 +00002127#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00002128 do { \
sewardj38de0992006-01-20 16:46:34 +00002129 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00002130 volatile unsigned long _argvec[3]; \
2131 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00002132 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00002133 _argvec[1] = (unsigned long)arg1; \
2134 _argvec[2] = (unsigned long)arg2; \
2135 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002136 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002137 "mr 11,%1\n\t" \
2138 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2139 "lwz 4,8(11)\n\t" \
2140 "lwz 11,0(11)\n\t" /* target->r11 */ \
2141 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002142 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002143 "mr %0,3" \
2144 : /*out*/ "=r" (_res) \
2145 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002146 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj0ec07f32006-01-12 12:32:32 +00002147 ); \
2148 lval = (__typeof__(lval)) _res; \
2149 } while (0)
2150
sewardjead61df2006-03-12 13:39:15 +00002151#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2152 do { \
2153 volatile OrigFn _orig = (orig); \
2154 volatile unsigned long _argvec[4]; \
2155 volatile unsigned long _res; \
2156 _argvec[0] = (unsigned long)_orig.nraddr; \
2157 _argvec[1] = (unsigned long)arg1; \
2158 _argvec[2] = (unsigned long)arg2; \
2159 _argvec[3] = (unsigned long)arg3; \
2160 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002161 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002162 "mr 11,%1\n\t" \
2163 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2164 "lwz 4,8(11)\n\t" \
2165 "lwz 5,12(11)\n\t" \
2166 "lwz 11,0(11)\n\t" /* target->r11 */ \
2167 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002168 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002169 "mr %0,3" \
2170 : /*out*/ "=r" (_res) \
2171 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002172 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002173 ); \
2174 lval = (__typeof__(lval)) _res; \
2175 } while (0)
2176
2177#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2178 do { \
2179 volatile OrigFn _orig = (orig); \
2180 volatile unsigned long _argvec[5]; \
2181 volatile unsigned long _res; \
2182 _argvec[0] = (unsigned long)_orig.nraddr; \
2183 _argvec[1] = (unsigned long)arg1; \
2184 _argvec[2] = (unsigned long)arg2; \
2185 _argvec[3] = (unsigned long)arg3; \
2186 _argvec[4] = (unsigned long)arg4; \
2187 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002188 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002189 "mr 11,%1\n\t" \
2190 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2191 "lwz 4,8(11)\n\t" \
2192 "lwz 5,12(11)\n\t" \
2193 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2194 "lwz 11,0(11)\n\t" /* target->r11 */ \
2195 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002196 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002197 "mr %0,3" \
2198 : /*out*/ "=r" (_res) \
2199 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002200 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002201 ); \
2202 lval = (__typeof__(lval)) _res; \
2203 } while (0)
2204
2205#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2206 do { \
2207 volatile OrigFn _orig = (orig); \
2208 volatile unsigned long _argvec[6]; \
2209 volatile unsigned long _res; \
2210 _argvec[0] = (unsigned long)_orig.nraddr; \
2211 _argvec[1] = (unsigned long)arg1; \
2212 _argvec[2] = (unsigned long)arg2; \
2213 _argvec[3] = (unsigned long)arg3; \
2214 _argvec[4] = (unsigned long)arg4; \
2215 _argvec[5] = (unsigned long)arg5; \
2216 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002217 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002218 "mr 11,%1\n\t" \
2219 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2220 "lwz 4,8(11)\n\t" \
2221 "lwz 5,12(11)\n\t" \
2222 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2223 "lwz 7,20(11)\n\t" \
2224 "lwz 11,0(11)\n\t" /* target->r11 */ \
2225 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002226 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002227 "mr %0,3" \
2228 : /*out*/ "=r" (_res) \
2229 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002230 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002231 ); \
2232 lval = (__typeof__(lval)) _res; \
2233 } while (0)
2234
2235#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2236 do { \
2237 volatile OrigFn _orig = (orig); \
2238 volatile unsigned long _argvec[7]; \
2239 volatile unsigned long _res; \
2240 _argvec[0] = (unsigned long)_orig.nraddr; \
2241 _argvec[1] = (unsigned long)arg1; \
2242 _argvec[2] = (unsigned long)arg2; \
2243 _argvec[3] = (unsigned long)arg3; \
2244 _argvec[4] = (unsigned long)arg4; \
2245 _argvec[5] = (unsigned long)arg5; \
2246 _argvec[6] = (unsigned long)arg6; \
2247 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002248 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002249 "mr 11,%1\n\t" \
2250 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2251 "lwz 4,8(11)\n\t" \
2252 "lwz 5,12(11)\n\t" \
2253 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2254 "lwz 7,20(11)\n\t" \
2255 "lwz 8,24(11)\n\t" \
2256 "lwz 11,0(11)\n\t" /* target->r11 */ \
2257 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002258 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002259 "mr %0,3" \
2260 : /*out*/ "=r" (_res) \
2261 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002262 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002263 ); \
2264 lval = (__typeof__(lval)) _res; \
2265 } while (0)
2266
2267#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2268 arg7) \
2269 do { \
2270 volatile OrigFn _orig = (orig); \
2271 volatile unsigned long _argvec[8]; \
2272 volatile unsigned long _res; \
2273 _argvec[0] = (unsigned long)_orig.nraddr; \
2274 _argvec[1] = (unsigned long)arg1; \
2275 _argvec[2] = (unsigned long)arg2; \
2276 _argvec[3] = (unsigned long)arg3; \
2277 _argvec[4] = (unsigned long)arg4; \
2278 _argvec[5] = (unsigned long)arg5; \
2279 _argvec[6] = (unsigned long)arg6; \
2280 _argvec[7] = (unsigned long)arg7; \
2281 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002282 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002283 "mr 11,%1\n\t" \
2284 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2285 "lwz 4,8(11)\n\t" \
2286 "lwz 5,12(11)\n\t" \
2287 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2288 "lwz 7,20(11)\n\t" \
2289 "lwz 8,24(11)\n\t" \
2290 "lwz 9,28(11)\n\t" \
2291 "lwz 11,0(11)\n\t" /* target->r11 */ \
2292 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002293 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002294 "mr %0,3" \
2295 : /*out*/ "=r" (_res) \
2296 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002297 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002298 ); \
2299 lval = (__typeof__(lval)) _res; \
2300 } while (0)
2301
2302#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2303 arg7,arg8) \
2304 do { \
2305 volatile OrigFn _orig = (orig); \
2306 volatile unsigned long _argvec[9]; \
2307 volatile unsigned long _res; \
2308 _argvec[0] = (unsigned long)_orig.nraddr; \
2309 _argvec[1] = (unsigned long)arg1; \
2310 _argvec[2] = (unsigned long)arg2; \
2311 _argvec[3] = (unsigned long)arg3; \
2312 _argvec[4] = (unsigned long)arg4; \
2313 _argvec[5] = (unsigned long)arg5; \
2314 _argvec[6] = (unsigned long)arg6; \
2315 _argvec[7] = (unsigned long)arg7; \
2316 _argvec[8] = (unsigned long)arg8; \
2317 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002318 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002319 "mr 11,%1\n\t" \
2320 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2321 "lwz 4,8(11)\n\t" \
2322 "lwz 5,12(11)\n\t" \
2323 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2324 "lwz 7,20(11)\n\t" \
2325 "lwz 8,24(11)\n\t" \
2326 "lwz 9,28(11)\n\t" \
2327 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2328 "lwz 11,0(11)\n\t" /* target->r11 */ \
2329 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002330 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002331 "mr %0,3" \
2332 : /*out*/ "=r" (_res) \
2333 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002334 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002335 ); \
2336 lval = (__typeof__(lval)) _res; \
2337 } while (0)
2338
2339#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2340 arg7,arg8,arg9) \
2341 do { \
2342 volatile OrigFn _orig = (orig); \
2343 volatile unsigned long _argvec[10]; \
2344 volatile unsigned long _res; \
2345 _argvec[0] = (unsigned long)_orig.nraddr; \
2346 _argvec[1] = (unsigned long)arg1; \
2347 _argvec[2] = (unsigned long)arg2; \
2348 _argvec[3] = (unsigned long)arg3; \
2349 _argvec[4] = (unsigned long)arg4; \
2350 _argvec[5] = (unsigned long)arg5; \
2351 _argvec[6] = (unsigned long)arg6; \
2352 _argvec[7] = (unsigned long)arg7; \
2353 _argvec[8] = (unsigned long)arg8; \
2354 _argvec[9] = (unsigned long)arg9; \
2355 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002356 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002357 "mr 11,%1\n\t" \
2358 "addi 1,1,-16\n\t" \
2359 /* arg9 */ \
2360 "lwz 3,36(11)\n\t" \
2361 "stw 3,8(1)\n\t" \
2362 /* args1-8 */ \
2363 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2364 "lwz 4,8(11)\n\t" \
2365 "lwz 5,12(11)\n\t" \
2366 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2367 "lwz 7,20(11)\n\t" \
2368 "lwz 8,24(11)\n\t" \
2369 "lwz 9,28(11)\n\t" \
2370 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2371 "lwz 11,0(11)\n\t" /* target->r11 */ \
2372 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002373 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002374 "mr %0,3" \
2375 : /*out*/ "=r" (_res) \
2376 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002377 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002378 ); \
2379 lval = (__typeof__(lval)) _res; \
2380 } while (0)
2381
2382#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2383 arg7,arg8,arg9,arg10) \
2384 do { \
2385 volatile OrigFn _orig = (orig); \
2386 volatile unsigned long _argvec[11]; \
2387 volatile unsigned long _res; \
2388 _argvec[0] = (unsigned long)_orig.nraddr; \
2389 _argvec[1] = (unsigned long)arg1; \
2390 _argvec[2] = (unsigned long)arg2; \
2391 _argvec[3] = (unsigned long)arg3; \
2392 _argvec[4] = (unsigned long)arg4; \
2393 _argvec[5] = (unsigned long)arg5; \
2394 _argvec[6] = (unsigned long)arg6; \
2395 _argvec[7] = (unsigned long)arg7; \
2396 _argvec[8] = (unsigned long)arg8; \
2397 _argvec[9] = (unsigned long)arg9; \
2398 _argvec[10] = (unsigned long)arg10; \
2399 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002400 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002401 "mr 11,%1\n\t" \
2402 "addi 1,1,-16\n\t" \
2403 /* arg10 */ \
2404 "lwz 3,40(11)\n\t" \
2405 "stw 3,12(1)\n\t" \
2406 /* arg9 */ \
2407 "lwz 3,36(11)\n\t" \
2408 "stw 3,8(1)\n\t" \
2409 /* args1-8 */ \
2410 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2411 "lwz 4,8(11)\n\t" \
2412 "lwz 5,12(11)\n\t" \
2413 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2414 "lwz 7,20(11)\n\t" \
2415 "lwz 8,24(11)\n\t" \
2416 "lwz 9,28(11)\n\t" \
2417 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2418 "lwz 11,0(11)\n\t" /* target->r11 */ \
2419 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002420 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002421 "mr %0,3" \
2422 : /*out*/ "=r" (_res) \
2423 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002424 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002425 ); \
2426 lval = (__typeof__(lval)) _res; \
2427 } while (0)
2428
2429#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2430 arg7,arg8,arg9,arg10,arg11) \
2431 do { \
2432 volatile OrigFn _orig = (orig); \
2433 volatile unsigned long _argvec[12]; \
2434 volatile unsigned long _res; \
2435 _argvec[0] = (unsigned long)_orig.nraddr; \
2436 _argvec[1] = (unsigned long)arg1; \
2437 _argvec[2] = (unsigned long)arg2; \
2438 _argvec[3] = (unsigned long)arg3; \
2439 _argvec[4] = (unsigned long)arg4; \
2440 _argvec[5] = (unsigned long)arg5; \
2441 _argvec[6] = (unsigned long)arg6; \
2442 _argvec[7] = (unsigned long)arg7; \
2443 _argvec[8] = (unsigned long)arg8; \
2444 _argvec[9] = (unsigned long)arg9; \
2445 _argvec[10] = (unsigned long)arg10; \
2446 _argvec[11] = (unsigned long)arg11; \
2447 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002448 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002449 "mr 11,%1\n\t" \
2450 "addi 1,1,-32\n\t" \
2451 /* arg11 */ \
2452 "lwz 3,44(11)\n\t" \
2453 "stw 3,16(1)\n\t" \
2454 /* arg10 */ \
2455 "lwz 3,40(11)\n\t" \
2456 "stw 3,12(1)\n\t" \
2457 /* arg9 */ \
2458 "lwz 3,36(11)\n\t" \
2459 "stw 3,8(1)\n\t" \
2460 /* args1-8 */ \
2461 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2462 "lwz 4,8(11)\n\t" \
2463 "lwz 5,12(11)\n\t" \
2464 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2465 "lwz 7,20(11)\n\t" \
2466 "lwz 8,24(11)\n\t" \
2467 "lwz 9,28(11)\n\t" \
2468 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2469 "lwz 11,0(11)\n\t" /* target->r11 */ \
2470 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002471 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002472 "mr %0,3" \
2473 : /*out*/ "=r" (_res) \
2474 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002475 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002476 ); \
2477 lval = (__typeof__(lval)) _res; \
2478 } while (0)
2479
2480#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2481 arg7,arg8,arg9,arg10,arg11,arg12) \
2482 do { \
2483 volatile OrigFn _orig = (orig); \
2484 volatile unsigned long _argvec[13]; \
2485 volatile unsigned long _res; \
2486 _argvec[0] = (unsigned long)_orig.nraddr; \
2487 _argvec[1] = (unsigned long)arg1; \
2488 _argvec[2] = (unsigned long)arg2; \
2489 _argvec[3] = (unsigned long)arg3; \
2490 _argvec[4] = (unsigned long)arg4; \
2491 _argvec[5] = (unsigned long)arg5; \
2492 _argvec[6] = (unsigned long)arg6; \
2493 _argvec[7] = (unsigned long)arg7; \
2494 _argvec[8] = (unsigned long)arg8; \
2495 _argvec[9] = (unsigned long)arg9; \
2496 _argvec[10] = (unsigned long)arg10; \
2497 _argvec[11] = (unsigned long)arg11; \
2498 _argvec[12] = (unsigned long)arg12; \
2499 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002500 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002501 "mr 11,%1\n\t" \
2502 "addi 1,1,-32\n\t" \
2503 /* arg12 */ \
2504 "lwz 3,48(11)\n\t" \
2505 "stw 3,20(1)\n\t" \
2506 /* arg11 */ \
2507 "lwz 3,44(11)\n\t" \
2508 "stw 3,16(1)\n\t" \
2509 /* arg10 */ \
2510 "lwz 3,40(11)\n\t" \
2511 "stw 3,12(1)\n\t" \
2512 /* arg9 */ \
2513 "lwz 3,36(11)\n\t" \
2514 "stw 3,8(1)\n\t" \
2515 /* args1-8 */ \
2516 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2517 "lwz 4,8(11)\n\t" \
2518 "lwz 5,12(11)\n\t" \
2519 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2520 "lwz 7,20(11)\n\t" \
2521 "lwz 8,24(11)\n\t" \
2522 "lwz 9,28(11)\n\t" \
2523 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2524 "lwz 11,0(11)\n\t" /* target->r11 */ \
2525 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002526 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002527 "mr %0,3" \
2528 : /*out*/ "=r" (_res) \
2529 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002530 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002531 ); \
2532 lval = (__typeof__(lval)) _res; \
2533 } while (0)
2534
sewardjf5c1a7f2006-10-17 01:32:48 +00002535#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +00002536
sewardjf5c1a7f2006-10-17 01:32:48 +00002537/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002538
sewardjf5c1a7f2006-10-17 01:32:48 +00002539#if defined(PLAT_ppc64_linux)
sewardj9734b202006-01-17 01:49:37 +00002540
2541/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2542
2543/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00002544#define __CALLER_SAVED_REGS \
2545 "lr", "ctr", "xer", \
2546 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2547 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2548 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00002549
tom4118e0f2012-08-02 09:23:45 +00002550/* Macros to save and align the stack before making a function
2551 call and restore it afterwards as gcc may not keep the stack
2552 pointer aligned if it doesn't realise calls are being made
2553 to other functions. */
2554
2555#define VALGRIND_ALIGN_STACK \
2556 "mr 28,1\n\t" \
2557 "rldicr 1,1,0,59\n\t"
2558#define VALGRIND_RESTORE_STACK \
2559 "mr 1,28\n\t"
2560
sewardj9734b202006-01-17 01:49:37 +00002561/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2562 long) == 8. */
2563
sewardjd68ac3e2006-01-20 14:31:57 +00002564#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00002565 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002566 volatile OrigFn _orig = (orig); \
2567 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00002568 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002569 /* _argvec[0] holds current r2 across the call */ \
2570 _argvec[1] = (unsigned long)_orig.r2; \
2571 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00002572 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002573 VALGRIND_ALIGN_STACK \
sewardj9734b202006-01-17 01:49:37 +00002574 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002575 "std 2,-16(11)\n\t" /* save tocptr */ \
2576 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2577 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002578 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2579 "mr 11,%1\n\t" \
2580 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002581 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2582 VALGRIND_RESTORE_STACK \
sewardj9734b202006-01-17 01:49:37 +00002583 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002584 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002585 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj9734b202006-01-17 01:49:37 +00002586 ); \
2587 lval = (__typeof__(lval)) _res; \
2588 } while (0)
2589
sewardjd68ac3e2006-01-20 14:31:57 +00002590#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00002591 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002592 volatile OrigFn _orig = (orig); \
2593 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00002594 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002595 /* _argvec[0] holds current r2 across the call */ \
2596 _argvec[1] = (unsigned long)_orig.r2; \
2597 _argvec[2] = (unsigned long)_orig.nraddr; \
2598 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00002599 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002600 VALGRIND_ALIGN_STACK \
sewardj9734b202006-01-17 01:49:37 +00002601 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002602 "std 2,-16(11)\n\t" /* save tocptr */ \
2603 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2604 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2605 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002606 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2607 "mr 11,%1\n\t" \
2608 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002609 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2610 VALGRIND_RESTORE_STACK \
sewardj9734b202006-01-17 01:49:37 +00002611 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002612 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002613 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj9734b202006-01-17 01:49:37 +00002614 ); \
2615 lval = (__typeof__(lval)) _res; \
2616 } while (0)
2617
sewardjd68ac3e2006-01-20 14:31:57 +00002618#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00002619 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002620 volatile OrigFn _orig = (orig); \
2621 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00002622 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002623 /* _argvec[0] holds current r2 across the call */ \
2624 _argvec[1] = (unsigned long)_orig.r2; \
2625 _argvec[2] = (unsigned long)_orig.nraddr; \
2626 _argvec[2+1] = (unsigned long)arg1; \
2627 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00002628 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002629 VALGRIND_ALIGN_STACK \
sewardj9734b202006-01-17 01:49:37 +00002630 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002631 "std 2,-16(11)\n\t" /* save tocptr */ \
2632 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2633 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00002634 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00002635 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002636 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2637 "mr 11,%1\n\t" \
2638 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002639 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2640 VALGRIND_RESTORE_STACK \
sewardj9734b202006-01-17 01:49:37 +00002641 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002642 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002643 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj9734b202006-01-17 01:49:37 +00002644 ); \
2645 lval = (__typeof__(lval)) _res; \
2646 } while (0)
2647
sewardjcd636392006-03-12 16:48:14 +00002648#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2649 do { \
2650 volatile OrigFn _orig = (orig); \
2651 volatile unsigned long _argvec[3+3]; \
2652 volatile unsigned long _res; \
2653 /* _argvec[0] holds current r2 across the call */ \
2654 _argvec[1] = (unsigned long)_orig.r2; \
2655 _argvec[2] = (unsigned long)_orig.nraddr; \
2656 _argvec[2+1] = (unsigned long)arg1; \
2657 _argvec[2+2] = (unsigned long)arg2; \
2658 _argvec[2+3] = (unsigned long)arg3; \
2659 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002660 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002661 "mr 11,%1\n\t" \
2662 "std 2,-16(11)\n\t" /* save tocptr */ \
2663 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2664 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2665 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2666 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2667 "ld 11, 0(11)\n\t" /* target->r11 */ \
2668 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2669 "mr 11,%1\n\t" \
2670 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002671 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2672 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002673 : /*out*/ "=r" (_res) \
2674 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002675 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002676 ); \
2677 lval = (__typeof__(lval)) _res; \
2678 } while (0)
2679
2680#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2681 do { \
2682 volatile OrigFn _orig = (orig); \
2683 volatile unsigned long _argvec[3+4]; \
2684 volatile unsigned long _res; \
2685 /* _argvec[0] holds current r2 across the call */ \
2686 _argvec[1] = (unsigned long)_orig.r2; \
2687 _argvec[2] = (unsigned long)_orig.nraddr; \
2688 _argvec[2+1] = (unsigned long)arg1; \
2689 _argvec[2+2] = (unsigned long)arg2; \
2690 _argvec[2+3] = (unsigned long)arg3; \
2691 _argvec[2+4] = (unsigned long)arg4; \
2692 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002693 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002694 "mr 11,%1\n\t" \
2695 "std 2,-16(11)\n\t" /* save tocptr */ \
2696 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2697 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2698 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2699 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2700 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2701 "ld 11, 0(11)\n\t" /* target->r11 */ \
2702 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2703 "mr 11,%1\n\t" \
2704 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002705 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2706 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002707 : /*out*/ "=r" (_res) \
2708 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002709 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002710 ); \
2711 lval = (__typeof__(lval)) _res; \
2712 } while (0)
2713
2714#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2715 do { \
2716 volatile OrigFn _orig = (orig); \
2717 volatile unsigned long _argvec[3+5]; \
2718 volatile unsigned long _res; \
2719 /* _argvec[0] holds current r2 across the call */ \
2720 _argvec[1] = (unsigned long)_orig.r2; \
2721 _argvec[2] = (unsigned long)_orig.nraddr; \
2722 _argvec[2+1] = (unsigned long)arg1; \
2723 _argvec[2+2] = (unsigned long)arg2; \
2724 _argvec[2+3] = (unsigned long)arg3; \
2725 _argvec[2+4] = (unsigned long)arg4; \
2726 _argvec[2+5] = (unsigned long)arg5; \
2727 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002728 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002729 "mr 11,%1\n\t" \
2730 "std 2,-16(11)\n\t" /* save tocptr */ \
2731 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2732 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2733 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2734 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2735 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2736 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2737 "ld 11, 0(11)\n\t" /* target->r11 */ \
2738 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2739 "mr 11,%1\n\t" \
2740 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002741 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2742 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002743 : /*out*/ "=r" (_res) \
2744 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002745 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002746 ); \
2747 lval = (__typeof__(lval)) _res; \
2748 } while (0)
2749
2750#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2751 do { \
2752 volatile OrigFn _orig = (orig); \
2753 volatile unsigned long _argvec[3+6]; \
2754 volatile unsigned long _res; \
2755 /* _argvec[0] holds current r2 across the call */ \
2756 _argvec[1] = (unsigned long)_orig.r2; \
2757 _argvec[2] = (unsigned long)_orig.nraddr; \
2758 _argvec[2+1] = (unsigned long)arg1; \
2759 _argvec[2+2] = (unsigned long)arg2; \
2760 _argvec[2+3] = (unsigned long)arg3; \
2761 _argvec[2+4] = (unsigned long)arg4; \
2762 _argvec[2+5] = (unsigned long)arg5; \
2763 _argvec[2+6] = (unsigned long)arg6; \
2764 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002765 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002766 "mr 11,%1\n\t" \
2767 "std 2,-16(11)\n\t" /* save tocptr */ \
2768 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2769 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2770 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2771 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2772 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2773 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2774 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2775 "ld 11, 0(11)\n\t" /* target->r11 */ \
2776 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2777 "mr 11,%1\n\t" \
2778 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002779 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2780 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002781 : /*out*/ "=r" (_res) \
2782 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002783 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002784 ); \
2785 lval = (__typeof__(lval)) _res; \
2786 } while (0)
2787
2788#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2789 arg7) \
2790 do { \
2791 volatile OrigFn _orig = (orig); \
2792 volatile unsigned long _argvec[3+7]; \
2793 volatile unsigned long _res; \
2794 /* _argvec[0] holds current r2 across the call */ \
2795 _argvec[1] = (unsigned long)_orig.r2; \
2796 _argvec[2] = (unsigned long)_orig.nraddr; \
2797 _argvec[2+1] = (unsigned long)arg1; \
2798 _argvec[2+2] = (unsigned long)arg2; \
2799 _argvec[2+3] = (unsigned long)arg3; \
2800 _argvec[2+4] = (unsigned long)arg4; \
2801 _argvec[2+5] = (unsigned long)arg5; \
2802 _argvec[2+6] = (unsigned long)arg6; \
2803 _argvec[2+7] = (unsigned long)arg7; \
2804 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002805 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002806 "mr 11,%1\n\t" \
2807 "std 2,-16(11)\n\t" /* save tocptr */ \
2808 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2809 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2810 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2811 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2812 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2813 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2814 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2815 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2816 "ld 11, 0(11)\n\t" /* target->r11 */ \
2817 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2818 "mr 11,%1\n\t" \
2819 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002820 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2821 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002822 : /*out*/ "=r" (_res) \
2823 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002824 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002825 ); \
2826 lval = (__typeof__(lval)) _res; \
2827 } while (0)
2828
2829#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2830 arg7,arg8) \
2831 do { \
2832 volatile OrigFn _orig = (orig); \
2833 volatile unsigned long _argvec[3+8]; \
2834 volatile unsigned long _res; \
2835 /* _argvec[0] holds current r2 across the call */ \
2836 _argvec[1] = (unsigned long)_orig.r2; \
2837 _argvec[2] = (unsigned long)_orig.nraddr; \
2838 _argvec[2+1] = (unsigned long)arg1; \
2839 _argvec[2+2] = (unsigned long)arg2; \
2840 _argvec[2+3] = (unsigned long)arg3; \
2841 _argvec[2+4] = (unsigned long)arg4; \
2842 _argvec[2+5] = (unsigned long)arg5; \
2843 _argvec[2+6] = (unsigned long)arg6; \
2844 _argvec[2+7] = (unsigned long)arg7; \
2845 _argvec[2+8] = (unsigned long)arg8; \
2846 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002847 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002848 "mr 11,%1\n\t" \
2849 "std 2,-16(11)\n\t" /* save tocptr */ \
2850 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2851 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2852 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2853 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2854 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2855 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2856 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2857 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2858 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2859 "ld 11, 0(11)\n\t" /* target->r11 */ \
2860 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2861 "mr 11,%1\n\t" \
2862 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002863 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2864 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002865 : /*out*/ "=r" (_res) \
2866 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002867 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002868 ); \
2869 lval = (__typeof__(lval)) _res; \
2870 } while (0)
2871
2872#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2873 arg7,arg8,arg9) \
2874 do { \
2875 volatile OrigFn _orig = (orig); \
2876 volatile unsigned long _argvec[3+9]; \
2877 volatile unsigned long _res; \
2878 /* _argvec[0] holds current r2 across the call */ \
2879 _argvec[1] = (unsigned long)_orig.r2; \
2880 _argvec[2] = (unsigned long)_orig.nraddr; \
2881 _argvec[2+1] = (unsigned long)arg1; \
2882 _argvec[2+2] = (unsigned long)arg2; \
2883 _argvec[2+3] = (unsigned long)arg3; \
2884 _argvec[2+4] = (unsigned long)arg4; \
2885 _argvec[2+5] = (unsigned long)arg5; \
2886 _argvec[2+6] = (unsigned long)arg6; \
2887 _argvec[2+7] = (unsigned long)arg7; \
2888 _argvec[2+8] = (unsigned long)arg8; \
2889 _argvec[2+9] = (unsigned long)arg9; \
2890 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002891 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002892 "mr 11,%1\n\t" \
2893 "std 2,-16(11)\n\t" /* save tocptr */ \
2894 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2895 "addi 1,1,-128\n\t" /* expand stack frame */ \
2896 /* arg9 */ \
2897 "ld 3,72(11)\n\t" \
2898 "std 3,112(1)\n\t" \
2899 /* args1-8 */ \
2900 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2901 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2902 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2903 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2904 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2905 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2906 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2907 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2908 "ld 11, 0(11)\n\t" /* target->r11 */ \
2909 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2910 "mr 11,%1\n\t" \
2911 "mr %0,3\n\t" \
2912 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00002913 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002914 : /*out*/ "=r" (_res) \
2915 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002916 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002917 ); \
2918 lval = (__typeof__(lval)) _res; \
2919 } while (0)
2920
2921#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2922 arg7,arg8,arg9,arg10) \
2923 do { \
2924 volatile OrigFn _orig = (orig); \
2925 volatile unsigned long _argvec[3+10]; \
2926 volatile unsigned long _res; \
2927 /* _argvec[0] holds current r2 across the call */ \
2928 _argvec[1] = (unsigned long)_orig.r2; \
2929 _argvec[2] = (unsigned long)_orig.nraddr; \
2930 _argvec[2+1] = (unsigned long)arg1; \
2931 _argvec[2+2] = (unsigned long)arg2; \
2932 _argvec[2+3] = (unsigned long)arg3; \
2933 _argvec[2+4] = (unsigned long)arg4; \
2934 _argvec[2+5] = (unsigned long)arg5; \
2935 _argvec[2+6] = (unsigned long)arg6; \
2936 _argvec[2+7] = (unsigned long)arg7; \
2937 _argvec[2+8] = (unsigned long)arg8; \
2938 _argvec[2+9] = (unsigned long)arg9; \
2939 _argvec[2+10] = (unsigned long)arg10; \
2940 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002941 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002942 "mr 11,%1\n\t" \
2943 "std 2,-16(11)\n\t" /* save tocptr */ \
2944 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2945 "addi 1,1,-128\n\t" /* expand stack frame */ \
2946 /* arg10 */ \
2947 "ld 3,80(11)\n\t" \
2948 "std 3,120(1)\n\t" \
2949 /* arg9 */ \
2950 "ld 3,72(11)\n\t" \
2951 "std 3,112(1)\n\t" \
2952 /* args1-8 */ \
2953 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2954 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2955 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2956 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2957 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2958 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2959 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2960 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2961 "ld 11, 0(11)\n\t" /* target->r11 */ \
2962 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2963 "mr 11,%1\n\t" \
2964 "mr %0,3\n\t" \
2965 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00002966 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002967 : /*out*/ "=r" (_res) \
2968 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002969 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002970 ); \
2971 lval = (__typeof__(lval)) _res; \
2972 } while (0)
2973
2974#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2975 arg7,arg8,arg9,arg10,arg11) \
2976 do { \
2977 volatile OrigFn _orig = (orig); \
2978 volatile unsigned long _argvec[3+11]; \
2979 volatile unsigned long _res; \
2980 /* _argvec[0] holds current r2 across the call */ \
2981 _argvec[1] = (unsigned long)_orig.r2; \
2982 _argvec[2] = (unsigned long)_orig.nraddr; \
2983 _argvec[2+1] = (unsigned long)arg1; \
2984 _argvec[2+2] = (unsigned long)arg2; \
2985 _argvec[2+3] = (unsigned long)arg3; \
2986 _argvec[2+4] = (unsigned long)arg4; \
2987 _argvec[2+5] = (unsigned long)arg5; \
2988 _argvec[2+6] = (unsigned long)arg6; \
2989 _argvec[2+7] = (unsigned long)arg7; \
2990 _argvec[2+8] = (unsigned long)arg8; \
2991 _argvec[2+9] = (unsigned long)arg9; \
2992 _argvec[2+10] = (unsigned long)arg10; \
2993 _argvec[2+11] = (unsigned long)arg11; \
2994 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002995 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002996 "mr 11,%1\n\t" \
2997 "std 2,-16(11)\n\t" /* save tocptr */ \
2998 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2999 "addi 1,1,-144\n\t" /* expand stack frame */ \
3000 /* arg11 */ \
3001 "ld 3,88(11)\n\t" \
3002 "std 3,128(1)\n\t" \
3003 /* arg10 */ \
3004 "ld 3,80(11)\n\t" \
3005 "std 3,120(1)\n\t" \
3006 /* arg9 */ \
3007 "ld 3,72(11)\n\t" \
3008 "std 3,112(1)\n\t" \
3009 /* args1-8 */ \
3010 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3011 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3012 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3013 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3014 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3015 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3016 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3017 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3018 "ld 11, 0(11)\n\t" /* target->r11 */ \
3019 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3020 "mr 11,%1\n\t" \
3021 "mr %0,3\n\t" \
3022 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00003023 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00003024 : /*out*/ "=r" (_res) \
3025 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00003026 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00003027 ); \
3028 lval = (__typeof__(lval)) _res; \
3029 } while (0)
3030
3031#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3032 arg7,arg8,arg9,arg10,arg11,arg12) \
3033 do { \
3034 volatile OrigFn _orig = (orig); \
3035 volatile unsigned long _argvec[3+12]; \
3036 volatile unsigned long _res; \
3037 /* _argvec[0] holds current r2 across the call */ \
3038 _argvec[1] = (unsigned long)_orig.r2; \
3039 _argvec[2] = (unsigned long)_orig.nraddr; \
3040 _argvec[2+1] = (unsigned long)arg1; \
3041 _argvec[2+2] = (unsigned long)arg2; \
3042 _argvec[2+3] = (unsigned long)arg3; \
3043 _argvec[2+4] = (unsigned long)arg4; \
3044 _argvec[2+5] = (unsigned long)arg5; \
3045 _argvec[2+6] = (unsigned long)arg6; \
3046 _argvec[2+7] = (unsigned long)arg7; \
3047 _argvec[2+8] = (unsigned long)arg8; \
3048 _argvec[2+9] = (unsigned long)arg9; \
3049 _argvec[2+10] = (unsigned long)arg10; \
3050 _argvec[2+11] = (unsigned long)arg11; \
3051 _argvec[2+12] = (unsigned long)arg12; \
3052 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003053 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00003054 "mr 11,%1\n\t" \
3055 "std 2,-16(11)\n\t" /* save tocptr */ \
3056 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3057 "addi 1,1,-144\n\t" /* expand stack frame */ \
3058 /* arg12 */ \
3059 "ld 3,96(11)\n\t" \
3060 "std 3,136(1)\n\t" \
3061 /* arg11 */ \
3062 "ld 3,88(11)\n\t" \
3063 "std 3,128(1)\n\t" \
3064 /* arg10 */ \
3065 "ld 3,80(11)\n\t" \
3066 "std 3,120(1)\n\t" \
3067 /* arg9 */ \
3068 "ld 3,72(11)\n\t" \
3069 "std 3,112(1)\n\t" \
3070 /* args1-8 */ \
3071 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3072 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3073 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3074 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3075 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3076 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3077 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3078 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3079 "ld 11, 0(11)\n\t" /* target->r11 */ \
3080 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3081 "mr 11,%1\n\t" \
3082 "mr %0,3\n\t" \
3083 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00003084 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00003085 : /*out*/ "=r" (_res) \
3086 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00003087 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00003088 ); \
3089 lval = (__typeof__(lval)) _res; \
3090 } while (0)
3091
sewardjf5c1a7f2006-10-17 01:32:48 +00003092#endif /* PLAT_ppc64_linux */
3093
sewardj59570ff2010-01-01 11:59:33 +00003094/* ------------------------- arm-linux ------------------------- */
3095
3096#if defined(PLAT_arm_linux)
3097
3098/* These regs are trashed by the hidden call. */
3099#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
3100
tom4118e0f2012-08-02 09:23:45 +00003101/* Macros to save and align the stack before making a function
3102 call and restore it afterwards as gcc may not keep the stack
3103 pointer aligned if it doesn't realise calls are being made
3104 to other functions. */
3105
sewardj567e5bb2012-08-04 19:23:54 +00003106/* This is a bit tricky. We store the original stack pointer in r10
3107 as it is callee-saves. gcc doesn't allow the use of r11 for some
3108 reason. Also, we can't directly "bic" the stack pointer in thumb
3109 mode since r13 isn't an allowed register number in that context.
3110 So use r4 as a temporary, since that is about to get trashed
3111 anyway, just after each use of this macro. Side effect is we need
3112 to be very careful about any future changes, since
3113 VALGRIND_ALIGN_STACK simply assumes r4 is usable. */
tom4118e0f2012-08-02 09:23:45 +00003114#define VALGRIND_ALIGN_STACK \
sewardj567e5bb2012-08-04 19:23:54 +00003115 "mov r10, sp\n\t" \
3116 "mov r4, sp\n\t" \
3117 "bic r4, r4, #7\n\t" \
3118 "mov sp, r4\n\t"
tom4118e0f2012-08-02 09:23:45 +00003119#define VALGRIND_RESTORE_STACK \
sewardj567e5bb2012-08-04 19:23:54 +00003120 "mov sp, r10\n\t"
tom4118e0f2012-08-02 09:23:45 +00003121
sewardj59570ff2010-01-01 11:59:33 +00003122/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
3123 long) == 4. */
3124
3125#define CALL_FN_W_v(lval, orig) \
3126 do { \
3127 volatile OrigFn _orig = (orig); \
3128 volatile unsigned long _argvec[1]; \
3129 volatile unsigned long _res; \
3130 _argvec[0] = (unsigned long)_orig.nraddr; \
3131 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003132 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003133 "ldr r4, [%1] \n\t" /* target->r4 */ \
3134 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003135 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003136 "mov %0, r0\n" \
3137 : /*out*/ "=r" (_res) \
3138 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003139 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003140 ); \
3141 lval = (__typeof__(lval)) _res; \
3142 } while (0)
3143
3144#define CALL_FN_W_W(lval, orig, arg1) \
3145 do { \
3146 volatile OrigFn _orig = (orig); \
3147 volatile unsigned long _argvec[2]; \
3148 volatile unsigned long _res; \
3149 _argvec[0] = (unsigned long)_orig.nraddr; \
3150 _argvec[1] = (unsigned long)(arg1); \
3151 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003152 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003153 "ldr r0, [%1, #4] \n\t" \
3154 "ldr r4, [%1] \n\t" /* target->r4 */ \
3155 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003156 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003157 "mov %0, r0\n" \
3158 : /*out*/ "=r" (_res) \
3159 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003160 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003161 ); \
3162 lval = (__typeof__(lval)) _res; \
3163 } while (0)
3164
3165#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3166 do { \
3167 volatile OrigFn _orig = (orig); \
3168 volatile unsigned long _argvec[3]; \
3169 volatile unsigned long _res; \
3170 _argvec[0] = (unsigned long)_orig.nraddr; \
3171 _argvec[1] = (unsigned long)(arg1); \
3172 _argvec[2] = (unsigned long)(arg2); \
3173 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003174 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003175 "ldr r0, [%1, #4] \n\t" \
3176 "ldr r1, [%1, #8] \n\t" \
3177 "ldr r4, [%1] \n\t" /* target->r4 */ \
3178 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003179 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003180 "mov %0, r0\n" \
3181 : /*out*/ "=r" (_res) \
3182 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003183 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003184 ); \
3185 lval = (__typeof__(lval)) _res; \
3186 } while (0)
3187
3188#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3189 do { \
3190 volatile OrigFn _orig = (orig); \
3191 volatile unsigned long _argvec[4]; \
3192 volatile unsigned long _res; \
3193 _argvec[0] = (unsigned long)_orig.nraddr; \
3194 _argvec[1] = (unsigned long)(arg1); \
3195 _argvec[2] = (unsigned long)(arg2); \
3196 _argvec[3] = (unsigned long)(arg3); \
3197 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003198 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003199 "ldr r0, [%1, #4] \n\t" \
3200 "ldr r1, [%1, #8] \n\t" \
3201 "ldr r2, [%1, #12] \n\t" \
3202 "ldr r4, [%1] \n\t" /* target->r4 */ \
3203 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003204 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003205 "mov %0, r0\n" \
3206 : /*out*/ "=r" (_res) \
3207 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003208 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003209 ); \
3210 lval = (__typeof__(lval)) _res; \
3211 } while (0)
3212
3213#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3214 do { \
3215 volatile OrigFn _orig = (orig); \
3216 volatile unsigned long _argvec[5]; \
3217 volatile unsigned long _res; \
3218 _argvec[0] = (unsigned long)_orig.nraddr; \
3219 _argvec[1] = (unsigned long)(arg1); \
3220 _argvec[2] = (unsigned long)(arg2); \
3221 _argvec[3] = (unsigned long)(arg3); \
3222 _argvec[4] = (unsigned long)(arg4); \
3223 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003224 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003225 "ldr r0, [%1, #4] \n\t" \
3226 "ldr r1, [%1, #8] \n\t" \
3227 "ldr r2, [%1, #12] \n\t" \
3228 "ldr r3, [%1, #16] \n\t" \
3229 "ldr r4, [%1] \n\t" /* target->r4 */ \
3230 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003231 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003232 "mov %0, r0" \
3233 : /*out*/ "=r" (_res) \
3234 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003235 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003236 ); \
3237 lval = (__typeof__(lval)) _res; \
3238 } while (0)
3239
3240#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3241 do { \
3242 volatile OrigFn _orig = (orig); \
3243 volatile unsigned long _argvec[6]; \
3244 volatile unsigned long _res; \
3245 _argvec[0] = (unsigned long)_orig.nraddr; \
3246 _argvec[1] = (unsigned long)(arg1); \
3247 _argvec[2] = (unsigned long)(arg2); \
3248 _argvec[3] = (unsigned long)(arg3); \
3249 _argvec[4] = (unsigned long)(arg4); \
3250 _argvec[5] = (unsigned long)(arg5); \
3251 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003252 VALGRIND_ALIGN_STACK \
3253 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003254 "ldr r0, [%1, #20] \n\t" \
3255 "push {r0} \n\t" \
3256 "ldr r0, [%1, #4] \n\t" \
3257 "ldr r1, [%1, #8] \n\t" \
3258 "ldr r2, [%1, #12] \n\t" \
3259 "ldr r3, [%1, #16] \n\t" \
3260 "ldr r4, [%1] \n\t" /* target->r4 */ \
3261 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003262 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003263 "mov %0, r0" \
3264 : /*out*/ "=r" (_res) \
3265 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003266 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003267 ); \
3268 lval = (__typeof__(lval)) _res; \
3269 } while (0)
3270
3271#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3272 do { \
3273 volatile OrigFn _orig = (orig); \
3274 volatile unsigned long _argvec[7]; \
3275 volatile unsigned long _res; \
3276 _argvec[0] = (unsigned long)_orig.nraddr; \
3277 _argvec[1] = (unsigned long)(arg1); \
3278 _argvec[2] = (unsigned long)(arg2); \
3279 _argvec[3] = (unsigned long)(arg3); \
3280 _argvec[4] = (unsigned long)(arg4); \
3281 _argvec[5] = (unsigned long)(arg5); \
3282 _argvec[6] = (unsigned long)(arg6); \
3283 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003284 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003285 "ldr r0, [%1, #20] \n\t" \
3286 "ldr r1, [%1, #24] \n\t" \
3287 "push {r0, r1} \n\t" \
3288 "ldr r0, [%1, #4] \n\t" \
3289 "ldr r1, [%1, #8] \n\t" \
3290 "ldr r2, [%1, #12] \n\t" \
3291 "ldr r3, [%1, #16] \n\t" \
3292 "ldr r4, [%1] \n\t" /* target->r4 */ \
3293 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003294 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003295 "mov %0, r0" \
3296 : /*out*/ "=r" (_res) \
3297 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003298 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003299 ); \
3300 lval = (__typeof__(lval)) _res; \
3301 } while (0)
3302
3303#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3304 arg7) \
3305 do { \
3306 volatile OrigFn _orig = (orig); \
3307 volatile unsigned long _argvec[8]; \
3308 volatile unsigned long _res; \
3309 _argvec[0] = (unsigned long)_orig.nraddr; \
3310 _argvec[1] = (unsigned long)(arg1); \
3311 _argvec[2] = (unsigned long)(arg2); \
3312 _argvec[3] = (unsigned long)(arg3); \
3313 _argvec[4] = (unsigned long)(arg4); \
3314 _argvec[5] = (unsigned long)(arg5); \
3315 _argvec[6] = (unsigned long)(arg6); \
3316 _argvec[7] = (unsigned long)(arg7); \
3317 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003318 VALGRIND_ALIGN_STACK \
3319 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003320 "ldr r0, [%1, #20] \n\t" \
3321 "ldr r1, [%1, #24] \n\t" \
3322 "ldr r2, [%1, #28] \n\t" \
3323 "push {r0, r1, r2} \n\t" \
3324 "ldr r0, [%1, #4] \n\t" \
3325 "ldr r1, [%1, #8] \n\t" \
3326 "ldr r2, [%1, #12] \n\t" \
3327 "ldr r3, [%1, #16] \n\t" \
3328 "ldr r4, [%1] \n\t" /* target->r4 */ \
3329 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003330 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003331 "mov %0, r0" \
3332 : /*out*/ "=r" (_res) \
3333 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003334 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003335 ); \
3336 lval = (__typeof__(lval)) _res; \
3337 } while (0)
3338
3339#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3340 arg7,arg8) \
3341 do { \
3342 volatile OrigFn _orig = (orig); \
3343 volatile unsigned long _argvec[9]; \
3344 volatile unsigned long _res; \
3345 _argvec[0] = (unsigned long)_orig.nraddr; \
3346 _argvec[1] = (unsigned long)(arg1); \
3347 _argvec[2] = (unsigned long)(arg2); \
3348 _argvec[3] = (unsigned long)(arg3); \
3349 _argvec[4] = (unsigned long)(arg4); \
3350 _argvec[5] = (unsigned long)(arg5); \
3351 _argvec[6] = (unsigned long)(arg6); \
3352 _argvec[7] = (unsigned long)(arg7); \
3353 _argvec[8] = (unsigned long)(arg8); \
3354 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003355 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003356 "ldr r0, [%1, #20] \n\t" \
3357 "ldr r1, [%1, #24] \n\t" \
3358 "ldr r2, [%1, #28] \n\t" \
3359 "ldr r3, [%1, #32] \n\t" \
3360 "push {r0, r1, r2, r3} \n\t" \
3361 "ldr r0, [%1, #4] \n\t" \
3362 "ldr r1, [%1, #8] \n\t" \
3363 "ldr r2, [%1, #12] \n\t" \
3364 "ldr r3, [%1, #16] \n\t" \
3365 "ldr r4, [%1] \n\t" /* target->r4 */ \
3366 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003367 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003368 "mov %0, r0" \
3369 : /*out*/ "=r" (_res) \
3370 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003371 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003372 ); \
3373 lval = (__typeof__(lval)) _res; \
3374 } while (0)
3375
3376#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3377 arg7,arg8,arg9) \
3378 do { \
3379 volatile OrigFn _orig = (orig); \
3380 volatile unsigned long _argvec[10]; \
3381 volatile unsigned long _res; \
3382 _argvec[0] = (unsigned long)_orig.nraddr; \
3383 _argvec[1] = (unsigned long)(arg1); \
3384 _argvec[2] = (unsigned long)(arg2); \
3385 _argvec[3] = (unsigned long)(arg3); \
3386 _argvec[4] = (unsigned long)(arg4); \
3387 _argvec[5] = (unsigned long)(arg5); \
3388 _argvec[6] = (unsigned long)(arg6); \
3389 _argvec[7] = (unsigned long)(arg7); \
3390 _argvec[8] = (unsigned long)(arg8); \
3391 _argvec[9] = (unsigned long)(arg9); \
3392 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003393 VALGRIND_ALIGN_STACK \
3394 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003395 "ldr r0, [%1, #20] \n\t" \
3396 "ldr r1, [%1, #24] \n\t" \
3397 "ldr r2, [%1, #28] \n\t" \
3398 "ldr r3, [%1, #32] \n\t" \
3399 "ldr r4, [%1, #36] \n\t" \
3400 "push {r0, r1, r2, r3, r4} \n\t" \
3401 "ldr r0, [%1, #4] \n\t" \
3402 "ldr r1, [%1, #8] \n\t" \
3403 "ldr r2, [%1, #12] \n\t" \
3404 "ldr r3, [%1, #16] \n\t" \
3405 "ldr r4, [%1] \n\t" /* target->r4 */ \
3406 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003407 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003408 "mov %0, r0" \
3409 : /*out*/ "=r" (_res) \
3410 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003411 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003412 ); \
3413 lval = (__typeof__(lval)) _res; \
3414 } while (0)
3415
3416#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3417 arg7,arg8,arg9,arg10) \
3418 do { \
3419 volatile OrigFn _orig = (orig); \
3420 volatile unsigned long _argvec[11]; \
3421 volatile unsigned long _res; \
3422 _argvec[0] = (unsigned long)_orig.nraddr; \
3423 _argvec[1] = (unsigned long)(arg1); \
3424 _argvec[2] = (unsigned long)(arg2); \
3425 _argvec[3] = (unsigned long)(arg3); \
3426 _argvec[4] = (unsigned long)(arg4); \
3427 _argvec[5] = (unsigned long)(arg5); \
3428 _argvec[6] = (unsigned long)(arg6); \
3429 _argvec[7] = (unsigned long)(arg7); \
3430 _argvec[8] = (unsigned long)(arg8); \
3431 _argvec[9] = (unsigned long)(arg9); \
3432 _argvec[10] = (unsigned long)(arg10); \
3433 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003434 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003435 "ldr r0, [%1, #40] \n\t" \
3436 "push {r0} \n\t" \
3437 "ldr r0, [%1, #20] \n\t" \
3438 "ldr r1, [%1, #24] \n\t" \
3439 "ldr r2, [%1, #28] \n\t" \
3440 "ldr r3, [%1, #32] \n\t" \
3441 "ldr r4, [%1, #36] \n\t" \
3442 "push {r0, r1, r2, r3, r4} \n\t" \
3443 "ldr r0, [%1, #4] \n\t" \
3444 "ldr r1, [%1, #8] \n\t" \
3445 "ldr r2, [%1, #12] \n\t" \
3446 "ldr r3, [%1, #16] \n\t" \
3447 "ldr r4, [%1] \n\t" /* target->r4 */ \
3448 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003449 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003450 "mov %0, r0" \
3451 : /*out*/ "=r" (_res) \
3452 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003453 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003454 ); \
3455 lval = (__typeof__(lval)) _res; \
3456 } while (0)
3457
3458#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3459 arg6,arg7,arg8,arg9,arg10, \
3460 arg11) \
3461 do { \
3462 volatile OrigFn _orig = (orig); \
3463 volatile unsigned long _argvec[12]; \
3464 volatile unsigned long _res; \
3465 _argvec[0] = (unsigned long)_orig.nraddr; \
3466 _argvec[1] = (unsigned long)(arg1); \
3467 _argvec[2] = (unsigned long)(arg2); \
3468 _argvec[3] = (unsigned long)(arg3); \
3469 _argvec[4] = (unsigned long)(arg4); \
3470 _argvec[5] = (unsigned long)(arg5); \
3471 _argvec[6] = (unsigned long)(arg6); \
3472 _argvec[7] = (unsigned long)(arg7); \
3473 _argvec[8] = (unsigned long)(arg8); \
3474 _argvec[9] = (unsigned long)(arg9); \
3475 _argvec[10] = (unsigned long)(arg10); \
3476 _argvec[11] = (unsigned long)(arg11); \
3477 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003478 VALGRIND_ALIGN_STACK \
3479 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003480 "ldr r0, [%1, #40] \n\t" \
3481 "ldr r1, [%1, #44] \n\t" \
3482 "push {r0, r1} \n\t" \
3483 "ldr r0, [%1, #20] \n\t" \
3484 "ldr r1, [%1, #24] \n\t" \
3485 "ldr r2, [%1, #28] \n\t" \
3486 "ldr r3, [%1, #32] \n\t" \
3487 "ldr r4, [%1, #36] \n\t" \
3488 "push {r0, r1, r2, r3, r4} \n\t" \
3489 "ldr r0, [%1, #4] \n\t" \
3490 "ldr r1, [%1, #8] \n\t" \
3491 "ldr r2, [%1, #12] \n\t" \
3492 "ldr r3, [%1, #16] \n\t" \
3493 "ldr r4, [%1] \n\t" /* target->r4 */ \
3494 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003495 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003496 "mov %0, r0" \
3497 : /*out*/ "=r" (_res) \
3498 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003499 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003500 ); \
3501 lval = (__typeof__(lval)) _res; \
3502 } while (0)
3503
3504#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3505 arg6,arg7,arg8,arg9,arg10, \
3506 arg11,arg12) \
3507 do { \
3508 volatile OrigFn _orig = (orig); \
3509 volatile unsigned long _argvec[13]; \
3510 volatile unsigned long _res; \
3511 _argvec[0] = (unsigned long)_orig.nraddr; \
3512 _argvec[1] = (unsigned long)(arg1); \
3513 _argvec[2] = (unsigned long)(arg2); \
3514 _argvec[3] = (unsigned long)(arg3); \
3515 _argvec[4] = (unsigned long)(arg4); \
3516 _argvec[5] = (unsigned long)(arg5); \
3517 _argvec[6] = (unsigned long)(arg6); \
3518 _argvec[7] = (unsigned long)(arg7); \
3519 _argvec[8] = (unsigned long)(arg8); \
3520 _argvec[9] = (unsigned long)(arg9); \
3521 _argvec[10] = (unsigned long)(arg10); \
3522 _argvec[11] = (unsigned long)(arg11); \
3523 _argvec[12] = (unsigned long)(arg12); \
3524 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003525 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003526 "ldr r0, [%1, #40] \n\t" \
3527 "ldr r1, [%1, #44] \n\t" \
3528 "ldr r2, [%1, #48] \n\t" \
3529 "push {r0, r1, r2} \n\t" \
3530 "ldr r0, [%1, #20] \n\t" \
3531 "ldr r1, [%1, #24] \n\t" \
3532 "ldr r2, [%1, #28] \n\t" \
3533 "ldr r3, [%1, #32] \n\t" \
3534 "ldr r4, [%1, #36] \n\t" \
3535 "push {r0, r1, r2, r3, r4} \n\t" \
3536 "ldr r0, [%1, #4] \n\t" \
3537 "ldr r1, [%1, #8] \n\t" \
3538 "ldr r2, [%1, #12] \n\t" \
3539 "ldr r3, [%1, #16] \n\t" \
3540 "ldr r4, [%1] \n\t" /* target->r4 */ \
3541 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003542 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003543 "mov %0, r0" \
3544 : /*out*/ "=r" (_res) \
3545 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003546 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003547 ); \
3548 lval = (__typeof__(lval)) _res; \
3549 } while (0)
3550
3551#endif /* PLAT_arm_linux */
3552
sewardjf0c12502014-01-12 12:54:00 +00003553/* ------------------------ arm64-linux ------------------------ */
3554
3555#if defined(PLAT_arm64_linux)
3556
3557/* These regs are trashed by the hidden call. */
3558#define __CALLER_SAVED_REGS \
3559 "x0", "x1", "x2", "x3","x4", "x5", "x6", "x7", "x8", "x9", \
3560 "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", \
sewardjbb9b1b92014-03-09 09:46:04 +00003561 "x18", "x19", "x20", "x30", \
sewardjf0c12502014-01-12 12:54:00 +00003562 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \
3563 "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", \
3564 "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", \
3565 "v26", "v27", "v28", "v29", "v30", "v31"
3566
sewardjbb9b1b92014-03-09 09:46:04 +00003567/* x21 is callee-saved, so we can use it to save and restore SP around
3568 the hidden call. */
3569#define VALGRIND_ALIGN_STACK \
3570 "mov x21, sp\n\t" \
3571 "bic sp, x21, #15\n\t"
3572#define VALGRIND_RESTORE_STACK \
3573 "mov sp, x21\n\t"
sewardjf0c12502014-01-12 12:54:00 +00003574
3575/* These CALL_FN_ macros assume that on arm64-linux,
3576 sizeof(unsigned long) == 8. */
3577
3578#define CALL_FN_W_v(lval, orig) \
3579 do { \
3580 volatile OrigFn _orig = (orig); \
3581 volatile unsigned long _argvec[1]; \
3582 volatile unsigned long _res; \
3583 _argvec[0] = (unsigned long)_orig.nraddr; \
3584 __asm__ volatile( \
3585 VALGRIND_ALIGN_STACK \
3586 "ldr x8, [%1] \n\t" /* target->x8 */ \
3587 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3588 VALGRIND_RESTORE_STACK \
3589 "mov %0, x0\n" \
3590 : /*out*/ "=r" (_res) \
3591 : /*in*/ "0" (&_argvec[0]) \
sewardjbb9b1b92014-03-09 09:46:04 +00003592 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00003593 ); \
3594 lval = (__typeof__(lval)) _res; \
3595 } while (0)
3596
3597#define CALL_FN_W_W(lval, orig, arg1) \
3598 do { \
3599 volatile OrigFn _orig = (orig); \
3600 volatile unsigned long _argvec[2]; \
3601 volatile unsigned long _res; \
3602 _argvec[0] = (unsigned long)_orig.nraddr; \
3603 _argvec[1] = (unsigned long)(arg1); \
3604 __asm__ volatile( \
3605 VALGRIND_ALIGN_STACK \
3606 "ldr x0, [%1, #8] \n\t" \
3607 "ldr x8, [%1] \n\t" /* target->x8 */ \
3608 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3609 VALGRIND_RESTORE_STACK \
3610 "mov %0, x0\n" \
3611 : /*out*/ "=r" (_res) \
3612 : /*in*/ "0" (&_argvec[0]) \
sewardjbb9b1b92014-03-09 09:46:04 +00003613 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00003614 ); \
3615 lval = (__typeof__(lval)) _res; \
3616 } while (0)
3617
3618#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3619 do { \
3620 volatile OrigFn _orig = (orig); \
3621 volatile unsigned long _argvec[3]; \
3622 volatile unsigned long _res; \
3623 _argvec[0] = (unsigned long)_orig.nraddr; \
3624 _argvec[1] = (unsigned long)(arg1); \
3625 _argvec[2] = (unsigned long)(arg2); \
3626 __asm__ volatile( \
3627 VALGRIND_ALIGN_STACK \
3628 "ldr x0, [%1, #8] \n\t" \
3629 "ldr x1, [%1, #16] \n\t" \
3630 "ldr x8, [%1] \n\t" /* target->x8 */ \
3631 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3632 VALGRIND_RESTORE_STACK \
3633 "mov %0, x0\n" \
3634 : /*out*/ "=r" (_res) \
3635 : /*in*/ "0" (&_argvec[0]) \
sewardj91e14602014-03-16 14:21:41 +00003636 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00003637 ); \
3638 lval = (__typeof__(lval)) _res; \
3639 } while (0)
3640
3641#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3642 do { \
3643 volatile OrigFn _orig = (orig); \
3644 volatile unsigned long _argvec[4]; \
3645 volatile unsigned long _res; \
3646 _argvec[0] = (unsigned long)_orig.nraddr; \
3647 _argvec[1] = (unsigned long)(arg1); \
3648 _argvec[2] = (unsigned long)(arg2); \
3649 _argvec[3] = (unsigned long)(arg3); \
3650 __asm__ volatile( \
3651 VALGRIND_ALIGN_STACK \
3652 "ldr x0, [%1, #8] \n\t" \
3653 "ldr x1, [%1, #16] \n\t" \
3654 "ldr x2, [%1, #24] \n\t" \
3655 "ldr x8, [%1] \n\t" /* target->x8 */ \
3656 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3657 VALGRIND_RESTORE_STACK \
3658 "mov %0, x0\n" \
3659 : /*out*/ "=r" (_res) \
3660 : /*in*/ "0" (&_argvec[0]) \
sewardj91e14602014-03-16 14:21:41 +00003661 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00003662 ); \
3663 lval = (__typeof__(lval)) _res; \
3664 } while (0)
3665
3666#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3667 do { \
3668 volatile OrigFn _orig = (orig); \
3669 volatile unsigned long _argvec[5]; \
3670 volatile unsigned long _res; \
3671 _argvec[0] = (unsigned long)_orig.nraddr; \
3672 _argvec[1] = (unsigned long)(arg1); \
3673 _argvec[2] = (unsigned long)(arg2); \
3674 _argvec[3] = (unsigned long)(arg3); \
3675 _argvec[4] = (unsigned long)(arg4); \
3676 __asm__ volatile( \
3677 VALGRIND_ALIGN_STACK \
3678 "ldr x0, [%1, #8] \n\t" \
3679 "ldr x1, [%1, #16] \n\t" \
3680 "ldr x2, [%1, #24] \n\t" \
3681 "ldr x3, [%1, #32] \n\t" \
3682 "ldr x8, [%1] \n\t" /* target->x8 */ \
3683 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3684 VALGRIND_RESTORE_STACK \
3685 "mov %0, x0" \
3686 : /*out*/ "=r" (_res) \
3687 : /*in*/ "0" (&_argvec[0]) \
sewardj91e14602014-03-16 14:21:41 +00003688 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3689 ); \
3690 lval = (__typeof__(lval)) _res; \
3691 } while (0)
3692
3693#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3694 do { \
3695 volatile OrigFn _orig = (orig); \
3696 volatile unsigned long _argvec[6]; \
3697 volatile unsigned long _res; \
3698 _argvec[0] = (unsigned long)_orig.nraddr; \
3699 _argvec[1] = (unsigned long)(arg1); \
3700 _argvec[2] = (unsigned long)(arg2); \
3701 _argvec[3] = (unsigned long)(arg3); \
3702 _argvec[4] = (unsigned long)(arg4); \
3703 _argvec[5] = (unsigned long)(arg5); \
3704 __asm__ volatile( \
3705 VALGRIND_ALIGN_STACK \
3706 "ldr x0, [%1, #8] \n\t" \
3707 "ldr x1, [%1, #16] \n\t" \
3708 "ldr x2, [%1, #24] \n\t" \
3709 "ldr x3, [%1, #32] \n\t" \
3710 "ldr x4, [%1, #40] \n\t" \
3711 "ldr x8, [%1] \n\t" /* target->x8 */ \
3712 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3713 VALGRIND_RESTORE_STACK \
3714 "mov %0, x0" \
3715 : /*out*/ "=r" (_res) \
3716 : /*in*/ "0" (&_argvec[0]) \
3717 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3718 ); \
3719 lval = (__typeof__(lval)) _res; \
3720 } while (0)
3721
3722#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3723 do { \
3724 volatile OrigFn _orig = (orig); \
3725 volatile unsigned long _argvec[7]; \
3726 volatile unsigned long _res; \
3727 _argvec[0] = (unsigned long)_orig.nraddr; \
3728 _argvec[1] = (unsigned long)(arg1); \
3729 _argvec[2] = (unsigned long)(arg2); \
3730 _argvec[3] = (unsigned long)(arg3); \
3731 _argvec[4] = (unsigned long)(arg4); \
3732 _argvec[5] = (unsigned long)(arg5); \
3733 _argvec[6] = (unsigned long)(arg6); \
3734 __asm__ volatile( \
3735 VALGRIND_ALIGN_STACK \
3736 "ldr x0, [%1, #8] \n\t" \
3737 "ldr x1, [%1, #16] \n\t" \
3738 "ldr x2, [%1, #24] \n\t" \
3739 "ldr x3, [%1, #32] \n\t" \
3740 "ldr x4, [%1, #40] \n\t" \
3741 "ldr x5, [%1, #48] \n\t" \
3742 "ldr x8, [%1] \n\t" /* target->x8 */ \
3743 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3744 VALGRIND_RESTORE_STACK \
3745 "mov %0, x0" \
3746 : /*out*/ "=r" (_res) \
3747 : /*in*/ "0" (&_argvec[0]) \
3748 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3749 ); \
3750 lval = (__typeof__(lval)) _res; \
3751 } while (0)
3752
3753#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3754 arg7) \
3755 do { \
3756 volatile OrigFn _orig = (orig); \
3757 volatile unsigned long _argvec[8]; \
3758 volatile unsigned long _res; \
3759 _argvec[0] = (unsigned long)_orig.nraddr; \
3760 _argvec[1] = (unsigned long)(arg1); \
3761 _argvec[2] = (unsigned long)(arg2); \
3762 _argvec[3] = (unsigned long)(arg3); \
3763 _argvec[4] = (unsigned long)(arg4); \
3764 _argvec[5] = (unsigned long)(arg5); \
3765 _argvec[6] = (unsigned long)(arg6); \
3766 _argvec[7] = (unsigned long)(arg7); \
3767 __asm__ volatile( \
3768 VALGRIND_ALIGN_STACK \
3769 "ldr x0, [%1, #8] \n\t" \
3770 "ldr x1, [%1, #16] \n\t" \
3771 "ldr x2, [%1, #24] \n\t" \
3772 "ldr x3, [%1, #32] \n\t" \
3773 "ldr x4, [%1, #40] \n\t" \
3774 "ldr x5, [%1, #48] \n\t" \
3775 "ldr x6, [%1, #56] \n\t" \
3776 "ldr x8, [%1] \n\t" /* target->x8 */ \
3777 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3778 VALGRIND_RESTORE_STACK \
3779 "mov %0, x0" \
3780 : /*out*/ "=r" (_res) \
3781 : /*in*/ "0" (&_argvec[0]) \
3782 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3783 ); \
3784 lval = (__typeof__(lval)) _res; \
3785 } while (0)
3786
3787#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3788 arg7,arg8) \
3789 do { \
3790 volatile OrigFn _orig = (orig); \
3791 volatile unsigned long _argvec[9]; \
3792 volatile unsigned long _res; \
3793 _argvec[0] = (unsigned long)_orig.nraddr; \
3794 _argvec[1] = (unsigned long)(arg1); \
3795 _argvec[2] = (unsigned long)(arg2); \
3796 _argvec[3] = (unsigned long)(arg3); \
3797 _argvec[4] = (unsigned long)(arg4); \
3798 _argvec[5] = (unsigned long)(arg5); \
3799 _argvec[6] = (unsigned long)(arg6); \
3800 _argvec[7] = (unsigned long)(arg7); \
3801 _argvec[8] = (unsigned long)(arg8); \
3802 __asm__ volatile( \
3803 VALGRIND_ALIGN_STACK \
3804 "ldr x0, [%1, #8] \n\t" \
3805 "ldr x1, [%1, #16] \n\t" \
3806 "ldr x2, [%1, #24] \n\t" \
3807 "ldr x3, [%1, #32] \n\t" \
3808 "ldr x4, [%1, #40] \n\t" \
3809 "ldr x5, [%1, #48] \n\t" \
3810 "ldr x6, [%1, #56] \n\t" \
3811 "ldr x7, [%1, #64] \n\t" \
3812 "ldr x8, [%1] \n\t" /* target->x8 */ \
3813 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3814 VALGRIND_RESTORE_STACK \
3815 "mov %0, x0" \
3816 : /*out*/ "=r" (_res) \
3817 : /*in*/ "0" (&_argvec[0]) \
3818 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3819 ); \
3820 lval = (__typeof__(lval)) _res; \
3821 } while (0)
3822
3823#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3824 arg7,arg8,arg9) \
3825 do { \
3826 volatile OrigFn _orig = (orig); \
3827 volatile unsigned long _argvec[10]; \
3828 volatile unsigned long _res; \
3829 _argvec[0] = (unsigned long)_orig.nraddr; \
3830 _argvec[1] = (unsigned long)(arg1); \
3831 _argvec[2] = (unsigned long)(arg2); \
3832 _argvec[3] = (unsigned long)(arg3); \
3833 _argvec[4] = (unsigned long)(arg4); \
3834 _argvec[5] = (unsigned long)(arg5); \
3835 _argvec[6] = (unsigned long)(arg6); \
3836 _argvec[7] = (unsigned long)(arg7); \
3837 _argvec[8] = (unsigned long)(arg8); \
3838 _argvec[9] = (unsigned long)(arg9); \
3839 __asm__ volatile( \
3840 VALGRIND_ALIGN_STACK \
3841 "sub sp, sp, #0x20 \n\t" \
3842 "ldr x0, [%1, #8] \n\t" \
3843 "ldr x1, [%1, #16] \n\t" \
3844 "ldr x2, [%1, #24] \n\t" \
3845 "ldr x3, [%1, #32] \n\t" \
3846 "ldr x4, [%1, #40] \n\t" \
3847 "ldr x5, [%1, #48] \n\t" \
3848 "ldr x6, [%1, #56] \n\t" \
3849 "ldr x7, [%1, #64] \n\t" \
3850 "ldr x8, [%1, #72] \n\t" \
3851 "str x8, [sp, #0] \n\t" \
3852 "ldr x8, [%1] \n\t" /* target->x8 */ \
3853 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3854 VALGRIND_RESTORE_STACK \
3855 "mov %0, x0" \
3856 : /*out*/ "=r" (_res) \
3857 : /*in*/ "0" (&_argvec[0]) \
3858 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3859 ); \
3860 lval = (__typeof__(lval)) _res; \
3861 } while (0)
3862
3863#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3864 arg7,arg8,arg9,arg10) \
3865 do { \
3866 volatile OrigFn _orig = (orig); \
3867 volatile unsigned long _argvec[11]; \
3868 volatile unsigned long _res; \
3869 _argvec[0] = (unsigned long)_orig.nraddr; \
3870 _argvec[1] = (unsigned long)(arg1); \
3871 _argvec[2] = (unsigned long)(arg2); \
3872 _argvec[3] = (unsigned long)(arg3); \
3873 _argvec[4] = (unsigned long)(arg4); \
3874 _argvec[5] = (unsigned long)(arg5); \
3875 _argvec[6] = (unsigned long)(arg6); \
3876 _argvec[7] = (unsigned long)(arg7); \
3877 _argvec[8] = (unsigned long)(arg8); \
3878 _argvec[9] = (unsigned long)(arg9); \
3879 _argvec[10] = (unsigned long)(arg10); \
3880 __asm__ volatile( \
3881 VALGRIND_ALIGN_STACK \
3882 "sub sp, sp, #0x20 \n\t" \
3883 "ldr x0, [%1, #8] \n\t" \
3884 "ldr x1, [%1, #16] \n\t" \
3885 "ldr x2, [%1, #24] \n\t" \
3886 "ldr x3, [%1, #32] \n\t" \
3887 "ldr x4, [%1, #40] \n\t" \
3888 "ldr x5, [%1, #48] \n\t" \
3889 "ldr x6, [%1, #56] \n\t" \
3890 "ldr x7, [%1, #64] \n\t" \
3891 "ldr x8, [%1, #72] \n\t" \
3892 "str x8, [sp, #0] \n\t" \
3893 "ldr x8, [%1, #80] \n\t" \
3894 "str x8, [sp, #8] \n\t" \
3895 "ldr x8, [%1] \n\t" /* target->x8 */ \
3896 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3897 VALGRIND_RESTORE_STACK \
3898 "mov %0, x0" \
3899 : /*out*/ "=r" (_res) \
3900 : /*in*/ "0" (&_argvec[0]) \
3901 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3902 ); \
3903 lval = (__typeof__(lval)) _res; \
3904 } while (0)
3905
3906#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3907 arg7,arg8,arg9,arg10,arg11) \
3908 do { \
3909 volatile OrigFn _orig = (orig); \
3910 volatile unsigned long _argvec[12]; \
3911 volatile unsigned long _res; \
3912 _argvec[0] = (unsigned long)_orig.nraddr; \
3913 _argvec[1] = (unsigned long)(arg1); \
3914 _argvec[2] = (unsigned long)(arg2); \
3915 _argvec[3] = (unsigned long)(arg3); \
3916 _argvec[4] = (unsigned long)(arg4); \
3917 _argvec[5] = (unsigned long)(arg5); \
3918 _argvec[6] = (unsigned long)(arg6); \
3919 _argvec[7] = (unsigned long)(arg7); \
3920 _argvec[8] = (unsigned long)(arg8); \
3921 _argvec[9] = (unsigned long)(arg9); \
3922 _argvec[10] = (unsigned long)(arg10); \
3923 _argvec[11] = (unsigned long)(arg11); \
3924 __asm__ volatile( \
3925 VALGRIND_ALIGN_STACK \
3926 "sub sp, sp, #0x30 \n\t" \
3927 "ldr x0, [%1, #8] \n\t" \
3928 "ldr x1, [%1, #16] \n\t" \
3929 "ldr x2, [%1, #24] \n\t" \
3930 "ldr x3, [%1, #32] \n\t" \
3931 "ldr x4, [%1, #40] \n\t" \
3932 "ldr x5, [%1, #48] \n\t" \
3933 "ldr x6, [%1, #56] \n\t" \
3934 "ldr x7, [%1, #64] \n\t" \
3935 "ldr x8, [%1, #72] \n\t" \
3936 "str x8, [sp, #0] \n\t" \
3937 "ldr x8, [%1, #80] \n\t" \
3938 "str x8, [sp, #8] \n\t" \
3939 "ldr x8, [%1, #88] \n\t" \
3940 "str x8, [sp, #16] \n\t" \
3941 "ldr x8, [%1] \n\t" /* target->x8 */ \
3942 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3943 VALGRIND_RESTORE_STACK \
3944 "mov %0, x0" \
3945 : /*out*/ "=r" (_res) \
3946 : /*in*/ "0" (&_argvec[0]) \
3947 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3948 ); \
3949 lval = (__typeof__(lval)) _res; \
3950 } while (0)
3951
3952#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3953 arg7,arg8,arg9,arg10,arg11, \
3954 arg12) \
3955 do { \
3956 volatile OrigFn _orig = (orig); \
3957 volatile unsigned long _argvec[13]; \
3958 volatile unsigned long _res; \
3959 _argvec[0] = (unsigned long)_orig.nraddr; \
3960 _argvec[1] = (unsigned long)(arg1); \
3961 _argvec[2] = (unsigned long)(arg2); \
3962 _argvec[3] = (unsigned long)(arg3); \
3963 _argvec[4] = (unsigned long)(arg4); \
3964 _argvec[5] = (unsigned long)(arg5); \
3965 _argvec[6] = (unsigned long)(arg6); \
3966 _argvec[7] = (unsigned long)(arg7); \
3967 _argvec[8] = (unsigned long)(arg8); \
3968 _argvec[9] = (unsigned long)(arg9); \
3969 _argvec[10] = (unsigned long)(arg10); \
3970 _argvec[11] = (unsigned long)(arg11); \
3971 _argvec[12] = (unsigned long)(arg12); \
3972 __asm__ volatile( \
3973 VALGRIND_ALIGN_STACK \
3974 "sub sp, sp, #0x30 \n\t" \
3975 "ldr x0, [%1, #8] \n\t" \
3976 "ldr x1, [%1, #16] \n\t" \
3977 "ldr x2, [%1, #24] \n\t" \
3978 "ldr x3, [%1, #32] \n\t" \
3979 "ldr x4, [%1, #40] \n\t" \
3980 "ldr x5, [%1, #48] \n\t" \
3981 "ldr x6, [%1, #56] \n\t" \
3982 "ldr x7, [%1, #64] \n\t" \
3983 "ldr x8, [%1, #72] \n\t" \
3984 "str x8, [sp, #0] \n\t" \
3985 "ldr x8, [%1, #80] \n\t" \
3986 "str x8, [sp, #8] \n\t" \
3987 "ldr x8, [%1, #88] \n\t" \
3988 "str x8, [sp, #16] \n\t" \
3989 "ldr x8, [%1, #96] \n\t" \
3990 "str x8, [sp, #24] \n\t" \
3991 "ldr x8, [%1] \n\t" /* target->x8 */ \
3992 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3993 VALGRIND_RESTORE_STACK \
3994 "mov %0, x0" \
3995 : /*out*/ "=r" (_res) \
3996 : /*in*/ "0" (&_argvec[0]) \
3997 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00003998 ); \
3999 lval = (__typeof__(lval)) _res; \
4000 } while (0)
4001
4002#endif /* PLAT_arm64_linux */
4003
sewardjb5b87402011-03-07 16:05:35 +00004004/* ------------------------- s390x-linux ------------------------- */
4005
4006#if defined(PLAT_s390x_linux)
4007
4008/* Similar workaround as amd64 (see above), but we use r11 as frame
4009 pointer and save the old r11 in r7. r11 might be used for
4010 argvec, therefore we copy argvec in r1 since r1 is clobbered
4011 after the call anyway. */
4012#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
4013# define __FRAME_POINTER \
4014 ,"d"(__builtin_dwarf_cfa())
4015# define VALGRIND_CFI_PROLOGUE \
4016 ".cfi_remember_state\n\t" \
4017 "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */ \
4018 "lgr 7,11\n\t" \
4019 "lgr 11,%2\n\t" \
4020 ".cfi_def_cfa r11, 0\n\t"
4021# define VALGRIND_CFI_EPILOGUE \
4022 "lgr 11, 7\n\t" \
4023 ".cfi_restore_state\n\t"
4024#else
4025# define __FRAME_POINTER
4026# define VALGRIND_CFI_PROLOGUE \
4027 "lgr 1,%1\n\t"
4028# define VALGRIND_CFI_EPILOGUE
4029#endif
4030
florian9af940f2012-08-03 03:21:42 +00004031/* Nb: On s390 the stack pointer is properly aligned *at all times*
4032 according to the s390 GCC maintainer. (The ABI specification is not
4033 precise in this regard.) Therefore, VALGRIND_ALIGN_STACK and
4034 VALGRIND_RESTORE_STACK are not defined here. */
sewardjb5b87402011-03-07 16:05:35 +00004035
4036/* These regs are trashed by the hidden call. Note that we overwrite
4037 r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
4038 function a proper return address. All others are ABI defined call
4039 clobbers. */
4040#define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \
4041 "f0","f1","f2","f3","f4","f5","f6","f7"
4042
florian9af940f2012-08-03 03:21:42 +00004043/* Nb: Although r11 is modified in the asm snippets below (inside
4044 VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for
4045 two reasons:
4046 (1) r11 is restored in VALGRIND_CFI_EPILOGUE, so effectively it is not
4047 modified
4048 (2) GCC will complain that r11 cannot appear inside a clobber section,
4049 when compiled with -O -fno-omit-frame-pointer
4050 */
sewardjb5b87402011-03-07 16:05:35 +00004051
4052#define CALL_FN_W_v(lval, orig) \
4053 do { \
4054 volatile OrigFn _orig = (orig); \
4055 volatile unsigned long _argvec[1]; \
4056 volatile unsigned long _res; \
4057 _argvec[0] = (unsigned long)_orig.nraddr; \
4058 __asm__ volatile( \
4059 VALGRIND_CFI_PROLOGUE \
4060 "aghi 15,-160\n\t" \
4061 "lg 1, 0(1)\n\t" /* target->r1 */ \
4062 VALGRIND_CALL_NOREDIR_R1 \
4063 "lgr %0, 2\n\t" \
4064 "aghi 15,160\n\t" \
4065 VALGRIND_CFI_EPILOGUE \
4066 : /*out*/ "=d" (_res) \
4067 : /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \
4068 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4069 ); \
4070 lval = (__typeof__(lval)) _res; \
4071 } while (0)
4072
4073/* The call abi has the arguments in r2-r6 and stack */
4074#define CALL_FN_W_W(lval, orig, arg1) \
4075 do { \
4076 volatile OrigFn _orig = (orig); \
4077 volatile unsigned long _argvec[2]; \
4078 volatile unsigned long _res; \
4079 _argvec[0] = (unsigned long)_orig.nraddr; \
4080 _argvec[1] = (unsigned long)arg1; \
4081 __asm__ volatile( \
4082 VALGRIND_CFI_PROLOGUE \
4083 "aghi 15,-160\n\t" \
4084 "lg 2, 8(1)\n\t" \
4085 "lg 1, 0(1)\n\t" \
4086 VALGRIND_CALL_NOREDIR_R1 \
4087 "lgr %0, 2\n\t" \
4088 "aghi 15,160\n\t" \
4089 VALGRIND_CFI_EPILOGUE \
4090 : /*out*/ "=d" (_res) \
4091 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4092 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4093 ); \
4094 lval = (__typeof__(lval)) _res; \
4095 } while (0)
4096
4097#define CALL_FN_W_WW(lval, orig, arg1, arg2) \
4098 do { \
4099 volatile OrigFn _orig = (orig); \
4100 volatile unsigned long _argvec[3]; \
4101 volatile unsigned long _res; \
4102 _argvec[0] = (unsigned long)_orig.nraddr; \
4103 _argvec[1] = (unsigned long)arg1; \
4104 _argvec[2] = (unsigned long)arg2; \
4105 __asm__ volatile( \
4106 VALGRIND_CFI_PROLOGUE \
4107 "aghi 15,-160\n\t" \
4108 "lg 2, 8(1)\n\t" \
4109 "lg 3,16(1)\n\t" \
4110 "lg 1, 0(1)\n\t" \
4111 VALGRIND_CALL_NOREDIR_R1 \
4112 "lgr %0, 2\n\t" \
4113 "aghi 15,160\n\t" \
4114 VALGRIND_CFI_EPILOGUE \
4115 : /*out*/ "=d" (_res) \
4116 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4117 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4118 ); \
4119 lval = (__typeof__(lval)) _res; \
4120 } while (0)
4121
4122#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \
4123 do { \
4124 volatile OrigFn _orig = (orig); \
4125 volatile unsigned long _argvec[4]; \
4126 volatile unsigned long _res; \
4127 _argvec[0] = (unsigned long)_orig.nraddr; \
4128 _argvec[1] = (unsigned long)arg1; \
4129 _argvec[2] = (unsigned long)arg2; \
4130 _argvec[3] = (unsigned long)arg3; \
4131 __asm__ volatile( \
4132 VALGRIND_CFI_PROLOGUE \
4133 "aghi 15,-160\n\t" \
4134 "lg 2, 8(1)\n\t" \
4135 "lg 3,16(1)\n\t" \
4136 "lg 4,24(1)\n\t" \
4137 "lg 1, 0(1)\n\t" \
4138 VALGRIND_CALL_NOREDIR_R1 \
4139 "lgr %0, 2\n\t" \
4140 "aghi 15,160\n\t" \
4141 VALGRIND_CFI_EPILOGUE \
4142 : /*out*/ "=d" (_res) \
4143 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4144 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4145 ); \
4146 lval = (__typeof__(lval)) _res; \
4147 } while (0)
4148
4149#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \
4150 do { \
4151 volatile OrigFn _orig = (orig); \
4152 volatile unsigned long _argvec[5]; \
4153 volatile unsigned long _res; \
4154 _argvec[0] = (unsigned long)_orig.nraddr; \
4155 _argvec[1] = (unsigned long)arg1; \
4156 _argvec[2] = (unsigned long)arg2; \
4157 _argvec[3] = (unsigned long)arg3; \
4158 _argvec[4] = (unsigned long)arg4; \
4159 __asm__ volatile( \
4160 VALGRIND_CFI_PROLOGUE \
4161 "aghi 15,-160\n\t" \
4162 "lg 2, 8(1)\n\t" \
4163 "lg 3,16(1)\n\t" \
4164 "lg 4,24(1)\n\t" \
4165 "lg 5,32(1)\n\t" \
4166 "lg 1, 0(1)\n\t" \
4167 VALGRIND_CALL_NOREDIR_R1 \
4168 "lgr %0, 2\n\t" \
4169 "aghi 15,160\n\t" \
4170 VALGRIND_CFI_EPILOGUE \
4171 : /*out*/ "=d" (_res) \
4172 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4173 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4174 ); \
4175 lval = (__typeof__(lval)) _res; \
4176 } while (0)
4177
4178#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \
4179 do { \
4180 volatile OrigFn _orig = (orig); \
4181 volatile unsigned long _argvec[6]; \
4182 volatile unsigned long _res; \
4183 _argvec[0] = (unsigned long)_orig.nraddr; \
4184 _argvec[1] = (unsigned long)arg1; \
4185 _argvec[2] = (unsigned long)arg2; \
4186 _argvec[3] = (unsigned long)arg3; \
4187 _argvec[4] = (unsigned long)arg4; \
4188 _argvec[5] = (unsigned long)arg5; \
4189 __asm__ volatile( \
4190 VALGRIND_CFI_PROLOGUE \
4191 "aghi 15,-160\n\t" \
4192 "lg 2, 8(1)\n\t" \
4193 "lg 3,16(1)\n\t" \
4194 "lg 4,24(1)\n\t" \
4195 "lg 5,32(1)\n\t" \
4196 "lg 6,40(1)\n\t" \
4197 "lg 1, 0(1)\n\t" \
4198 VALGRIND_CALL_NOREDIR_R1 \
4199 "lgr %0, 2\n\t" \
4200 "aghi 15,160\n\t" \
4201 VALGRIND_CFI_EPILOGUE \
4202 : /*out*/ "=d" (_res) \
4203 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4204 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4205 ); \
4206 lval = (__typeof__(lval)) _res; \
4207 } while (0)
4208
4209#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4210 arg6) \
4211 do { \
4212 volatile OrigFn _orig = (orig); \
4213 volatile unsigned long _argvec[7]; \
4214 volatile unsigned long _res; \
4215 _argvec[0] = (unsigned long)_orig.nraddr; \
4216 _argvec[1] = (unsigned long)arg1; \
4217 _argvec[2] = (unsigned long)arg2; \
4218 _argvec[3] = (unsigned long)arg3; \
4219 _argvec[4] = (unsigned long)arg4; \
4220 _argvec[5] = (unsigned long)arg5; \
4221 _argvec[6] = (unsigned long)arg6; \
4222 __asm__ volatile( \
4223 VALGRIND_CFI_PROLOGUE \
4224 "aghi 15,-168\n\t" \
4225 "lg 2, 8(1)\n\t" \
4226 "lg 3,16(1)\n\t" \
4227 "lg 4,24(1)\n\t" \
4228 "lg 5,32(1)\n\t" \
4229 "lg 6,40(1)\n\t" \
4230 "mvc 160(8,15), 48(1)\n\t" \
4231 "lg 1, 0(1)\n\t" \
4232 VALGRIND_CALL_NOREDIR_R1 \
4233 "lgr %0, 2\n\t" \
4234 "aghi 15,168\n\t" \
4235 VALGRIND_CFI_EPILOGUE \
4236 : /*out*/ "=d" (_res) \
4237 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4238 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4239 ); \
4240 lval = (__typeof__(lval)) _res; \
4241 } while (0)
4242
4243#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4244 arg6, arg7) \
4245 do { \
4246 volatile OrigFn _orig = (orig); \
4247 volatile unsigned long _argvec[8]; \
4248 volatile unsigned long _res; \
4249 _argvec[0] = (unsigned long)_orig.nraddr; \
4250 _argvec[1] = (unsigned long)arg1; \
4251 _argvec[2] = (unsigned long)arg2; \
4252 _argvec[3] = (unsigned long)arg3; \
4253 _argvec[4] = (unsigned long)arg4; \
4254 _argvec[5] = (unsigned long)arg5; \
4255 _argvec[6] = (unsigned long)arg6; \
4256 _argvec[7] = (unsigned long)arg7; \
4257 __asm__ volatile( \
4258 VALGRIND_CFI_PROLOGUE \
4259 "aghi 15,-176\n\t" \
4260 "lg 2, 8(1)\n\t" \
4261 "lg 3,16(1)\n\t" \
4262 "lg 4,24(1)\n\t" \
4263 "lg 5,32(1)\n\t" \
4264 "lg 6,40(1)\n\t" \
4265 "mvc 160(8,15), 48(1)\n\t" \
4266 "mvc 168(8,15), 56(1)\n\t" \
4267 "lg 1, 0(1)\n\t" \
4268 VALGRIND_CALL_NOREDIR_R1 \
4269 "lgr %0, 2\n\t" \
4270 "aghi 15,176\n\t" \
4271 VALGRIND_CFI_EPILOGUE \
4272 : /*out*/ "=d" (_res) \
4273 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4274 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4275 ); \
4276 lval = (__typeof__(lval)) _res; \
4277 } while (0)
4278
4279#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4280 arg6, arg7 ,arg8) \
4281 do { \
4282 volatile OrigFn _orig = (orig); \
4283 volatile unsigned long _argvec[9]; \
4284 volatile unsigned long _res; \
4285 _argvec[0] = (unsigned long)_orig.nraddr; \
4286 _argvec[1] = (unsigned long)arg1; \
4287 _argvec[2] = (unsigned long)arg2; \
4288 _argvec[3] = (unsigned long)arg3; \
4289 _argvec[4] = (unsigned long)arg4; \
4290 _argvec[5] = (unsigned long)arg5; \
4291 _argvec[6] = (unsigned long)arg6; \
4292 _argvec[7] = (unsigned long)arg7; \
4293 _argvec[8] = (unsigned long)arg8; \
4294 __asm__ volatile( \
4295 VALGRIND_CFI_PROLOGUE \
4296 "aghi 15,-184\n\t" \
4297 "lg 2, 8(1)\n\t" \
4298 "lg 3,16(1)\n\t" \
4299 "lg 4,24(1)\n\t" \
4300 "lg 5,32(1)\n\t" \
4301 "lg 6,40(1)\n\t" \
4302 "mvc 160(8,15), 48(1)\n\t" \
4303 "mvc 168(8,15), 56(1)\n\t" \
4304 "mvc 176(8,15), 64(1)\n\t" \
4305 "lg 1, 0(1)\n\t" \
4306 VALGRIND_CALL_NOREDIR_R1 \
4307 "lgr %0, 2\n\t" \
4308 "aghi 15,184\n\t" \
4309 VALGRIND_CFI_EPILOGUE \
4310 : /*out*/ "=d" (_res) \
4311 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4312 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4313 ); \
4314 lval = (__typeof__(lval)) _res; \
4315 } while (0)
4316
4317#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4318 arg6, arg7 ,arg8, arg9) \
4319 do { \
4320 volatile OrigFn _orig = (orig); \
4321 volatile unsigned long _argvec[10]; \
4322 volatile unsigned long _res; \
4323 _argvec[0] = (unsigned long)_orig.nraddr; \
4324 _argvec[1] = (unsigned long)arg1; \
4325 _argvec[2] = (unsigned long)arg2; \
4326 _argvec[3] = (unsigned long)arg3; \
4327 _argvec[4] = (unsigned long)arg4; \
4328 _argvec[5] = (unsigned long)arg5; \
4329 _argvec[6] = (unsigned long)arg6; \
4330 _argvec[7] = (unsigned long)arg7; \
4331 _argvec[8] = (unsigned long)arg8; \
4332 _argvec[9] = (unsigned long)arg9; \
4333 __asm__ volatile( \
4334 VALGRIND_CFI_PROLOGUE \
4335 "aghi 15,-192\n\t" \
4336 "lg 2, 8(1)\n\t" \
4337 "lg 3,16(1)\n\t" \
4338 "lg 4,24(1)\n\t" \
4339 "lg 5,32(1)\n\t" \
4340 "lg 6,40(1)\n\t" \
4341 "mvc 160(8,15), 48(1)\n\t" \
4342 "mvc 168(8,15), 56(1)\n\t" \
4343 "mvc 176(8,15), 64(1)\n\t" \
4344 "mvc 184(8,15), 72(1)\n\t" \
4345 "lg 1, 0(1)\n\t" \
4346 VALGRIND_CALL_NOREDIR_R1 \
4347 "lgr %0, 2\n\t" \
4348 "aghi 15,192\n\t" \
4349 VALGRIND_CFI_EPILOGUE \
4350 : /*out*/ "=d" (_res) \
4351 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4352 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4353 ); \
4354 lval = (__typeof__(lval)) _res; \
4355 } while (0)
4356
4357#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4358 arg6, arg7 ,arg8, arg9, arg10) \
4359 do { \
4360 volatile OrigFn _orig = (orig); \
4361 volatile unsigned long _argvec[11]; \
4362 volatile unsigned long _res; \
4363 _argvec[0] = (unsigned long)_orig.nraddr; \
4364 _argvec[1] = (unsigned long)arg1; \
4365 _argvec[2] = (unsigned long)arg2; \
4366 _argvec[3] = (unsigned long)arg3; \
4367 _argvec[4] = (unsigned long)arg4; \
4368 _argvec[5] = (unsigned long)arg5; \
4369 _argvec[6] = (unsigned long)arg6; \
4370 _argvec[7] = (unsigned long)arg7; \
4371 _argvec[8] = (unsigned long)arg8; \
4372 _argvec[9] = (unsigned long)arg9; \
4373 _argvec[10] = (unsigned long)arg10; \
4374 __asm__ volatile( \
4375 VALGRIND_CFI_PROLOGUE \
4376 "aghi 15,-200\n\t" \
4377 "lg 2, 8(1)\n\t" \
4378 "lg 3,16(1)\n\t" \
4379 "lg 4,24(1)\n\t" \
4380 "lg 5,32(1)\n\t" \
4381 "lg 6,40(1)\n\t" \
4382 "mvc 160(8,15), 48(1)\n\t" \
4383 "mvc 168(8,15), 56(1)\n\t" \
4384 "mvc 176(8,15), 64(1)\n\t" \
4385 "mvc 184(8,15), 72(1)\n\t" \
4386 "mvc 192(8,15), 80(1)\n\t" \
4387 "lg 1, 0(1)\n\t" \
4388 VALGRIND_CALL_NOREDIR_R1 \
4389 "lgr %0, 2\n\t" \
4390 "aghi 15,200\n\t" \
4391 VALGRIND_CFI_EPILOGUE \
4392 : /*out*/ "=d" (_res) \
4393 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4394 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4395 ); \
4396 lval = (__typeof__(lval)) _res; \
4397 } while (0)
4398
4399#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4400 arg6, arg7 ,arg8, arg9, arg10, arg11) \
4401 do { \
4402 volatile OrigFn _orig = (orig); \
4403 volatile unsigned long _argvec[12]; \
4404 volatile unsigned long _res; \
4405 _argvec[0] = (unsigned long)_orig.nraddr; \
4406 _argvec[1] = (unsigned long)arg1; \
4407 _argvec[2] = (unsigned long)arg2; \
4408 _argvec[3] = (unsigned long)arg3; \
4409 _argvec[4] = (unsigned long)arg4; \
4410 _argvec[5] = (unsigned long)arg5; \
4411 _argvec[6] = (unsigned long)arg6; \
4412 _argvec[7] = (unsigned long)arg7; \
4413 _argvec[8] = (unsigned long)arg8; \
4414 _argvec[9] = (unsigned long)arg9; \
4415 _argvec[10] = (unsigned long)arg10; \
4416 _argvec[11] = (unsigned long)arg11; \
4417 __asm__ volatile( \
4418 VALGRIND_CFI_PROLOGUE \
4419 "aghi 15,-208\n\t" \
4420 "lg 2, 8(1)\n\t" \
4421 "lg 3,16(1)\n\t" \
4422 "lg 4,24(1)\n\t" \
4423 "lg 5,32(1)\n\t" \
4424 "lg 6,40(1)\n\t" \
4425 "mvc 160(8,15), 48(1)\n\t" \
4426 "mvc 168(8,15), 56(1)\n\t" \
4427 "mvc 176(8,15), 64(1)\n\t" \
4428 "mvc 184(8,15), 72(1)\n\t" \
4429 "mvc 192(8,15), 80(1)\n\t" \
4430 "mvc 200(8,15), 88(1)\n\t" \
4431 "lg 1, 0(1)\n\t" \
4432 VALGRIND_CALL_NOREDIR_R1 \
4433 "lgr %0, 2\n\t" \
4434 "aghi 15,208\n\t" \
4435 VALGRIND_CFI_EPILOGUE \
4436 : /*out*/ "=d" (_res) \
4437 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4438 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4439 ); \
4440 lval = (__typeof__(lval)) _res; \
4441 } while (0)
4442
4443#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4444 arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\
4445 do { \
4446 volatile OrigFn _orig = (orig); \
4447 volatile unsigned long _argvec[13]; \
4448 volatile unsigned long _res; \
4449 _argvec[0] = (unsigned long)_orig.nraddr; \
4450 _argvec[1] = (unsigned long)arg1; \
4451 _argvec[2] = (unsigned long)arg2; \
4452 _argvec[3] = (unsigned long)arg3; \
4453 _argvec[4] = (unsigned long)arg4; \
4454 _argvec[5] = (unsigned long)arg5; \
4455 _argvec[6] = (unsigned long)arg6; \
4456 _argvec[7] = (unsigned long)arg7; \
4457 _argvec[8] = (unsigned long)arg8; \
4458 _argvec[9] = (unsigned long)arg9; \
4459 _argvec[10] = (unsigned long)arg10; \
4460 _argvec[11] = (unsigned long)arg11; \
4461 _argvec[12] = (unsigned long)arg12; \
4462 __asm__ volatile( \
4463 VALGRIND_CFI_PROLOGUE \
4464 "aghi 15,-216\n\t" \
4465 "lg 2, 8(1)\n\t" \
4466 "lg 3,16(1)\n\t" \
4467 "lg 4,24(1)\n\t" \
4468 "lg 5,32(1)\n\t" \
4469 "lg 6,40(1)\n\t" \
4470 "mvc 160(8,15), 48(1)\n\t" \
4471 "mvc 168(8,15), 56(1)\n\t" \
4472 "mvc 176(8,15), 64(1)\n\t" \
4473 "mvc 184(8,15), 72(1)\n\t" \
4474 "mvc 192(8,15), 80(1)\n\t" \
4475 "mvc 200(8,15), 88(1)\n\t" \
4476 "mvc 208(8,15), 96(1)\n\t" \
4477 "lg 1, 0(1)\n\t" \
4478 VALGRIND_CALL_NOREDIR_R1 \
4479 "lgr %0, 2\n\t" \
4480 "aghi 15,216\n\t" \
4481 VALGRIND_CFI_EPILOGUE \
4482 : /*out*/ "=d" (_res) \
4483 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4484 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4485 ); \
4486 lval = (__typeof__(lval)) _res; \
4487 } while (0)
4488
4489
4490#endif /* PLAT_s390x_linux */
4491
petarj4df0bfc2013-02-27 23:17:33 +00004492/* ------------------------- mips32-linux ----------------------- */
sewardj5db15402012-06-07 09:13:21 +00004493
4494#if defined(PLAT_mips32_linux)
4495
4496/* These regs are trashed by the hidden call. */
4497#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \
4498"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
4499"$25", "$31"
4500
4501/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
4502 long) == 4. */
4503
4504#define CALL_FN_W_v(lval, orig) \
4505 do { \
4506 volatile OrigFn _orig = (orig); \
4507 volatile unsigned long _argvec[1]; \
4508 volatile unsigned long _res; \
4509 _argvec[0] = (unsigned long)_orig.nraddr; \
4510 __asm__ volatile( \
4511 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004512 "sw $28, 0($29) \n\t" \
4513 "sw $31, 4($29) \n\t" \
4514 "subu $29, $29, 16 \n\t" \
4515 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004516 VALGRIND_CALL_NOREDIR_T9 \
4517 "addu $29, $29, 16\n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004518 "lw $28, 0($29) \n\t" \
4519 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004520 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004521 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004522 : /*out*/ "=r" (_res) \
4523 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004524 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004525 ); \
4526 lval = (__typeof__(lval)) _res; \
4527 } while (0)
4528
4529#define CALL_FN_W_W(lval, orig, arg1) \
4530 do { \
4531 volatile OrigFn _orig = (orig); \
4532 volatile unsigned long _argvec[2]; \
4533 volatile unsigned long _res; \
4534 _argvec[0] = (unsigned long)_orig.nraddr; \
4535 _argvec[1] = (unsigned long)(arg1); \
4536 __asm__ volatile( \
4537 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004538 "sw $28, 0($29) \n\t" \
4539 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004540 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004541 "lw $4, 4(%1) \n\t" /* arg1*/ \
4542 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004543 VALGRIND_CALL_NOREDIR_T9 \
4544 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004545 "lw $28, 0($29) \n\t" \
4546 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004547 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004548 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004549 : /*out*/ "=r" (_res) \
petarj4df0bfc2013-02-27 23:17:33 +00004550 : /*in*/ "0" (&_argvec[0]) \
4551 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004552 ); \
4553 lval = (__typeof__(lval)) _res; \
4554 } while (0)
4555
4556#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
4557 do { \
4558 volatile OrigFn _orig = (orig); \
4559 volatile unsigned long _argvec[3]; \
4560 volatile unsigned long _res; \
4561 _argvec[0] = (unsigned long)_orig.nraddr; \
4562 _argvec[1] = (unsigned long)(arg1); \
4563 _argvec[2] = (unsigned long)(arg2); \
4564 __asm__ volatile( \
4565 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004566 "sw $28, 0($29) \n\t" \
4567 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004568 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004569 "lw $4, 4(%1) \n\t" \
4570 "lw $5, 8(%1) \n\t" \
4571 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004572 VALGRIND_CALL_NOREDIR_T9 \
4573 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004574 "lw $28, 0($29) \n\t" \
4575 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004576 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004577 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004578 : /*out*/ "=r" (_res) \
4579 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004580 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004581 ); \
4582 lval = (__typeof__(lval)) _res; \
4583 } while (0)
4584
4585#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
4586 do { \
4587 volatile OrigFn _orig = (orig); \
4588 volatile unsigned long _argvec[4]; \
4589 volatile unsigned long _res; \
4590 _argvec[0] = (unsigned long)_orig.nraddr; \
4591 _argvec[1] = (unsigned long)(arg1); \
4592 _argvec[2] = (unsigned long)(arg2); \
4593 _argvec[3] = (unsigned long)(arg3); \
4594 __asm__ volatile( \
4595 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004596 "sw $28, 0($29) \n\t" \
4597 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004598 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004599 "lw $4, 4(%1) \n\t" \
4600 "lw $5, 8(%1) \n\t" \
4601 "lw $6, 12(%1) \n\t" \
4602 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004603 VALGRIND_CALL_NOREDIR_T9 \
4604 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004605 "lw $28, 0($29) \n\t" \
4606 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004607 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004608 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004609 : /*out*/ "=r" (_res) \
4610 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004611 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004612 ); \
4613 lval = (__typeof__(lval)) _res; \
4614 } while (0)
4615
4616#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
4617 do { \
4618 volatile OrigFn _orig = (orig); \
4619 volatile unsigned long _argvec[5]; \
4620 volatile unsigned long _res; \
4621 _argvec[0] = (unsigned long)_orig.nraddr; \
4622 _argvec[1] = (unsigned long)(arg1); \
4623 _argvec[2] = (unsigned long)(arg2); \
4624 _argvec[3] = (unsigned long)(arg3); \
4625 _argvec[4] = (unsigned long)(arg4); \
4626 __asm__ volatile( \
4627 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004628 "sw $28, 0($29) \n\t" \
4629 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004630 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004631 "lw $4, 4(%1) \n\t" \
4632 "lw $5, 8(%1) \n\t" \
4633 "lw $6, 12(%1) \n\t" \
4634 "lw $7, 16(%1) \n\t" \
4635 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004636 VALGRIND_CALL_NOREDIR_T9 \
4637 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004638 "lw $28, 0($29) \n\t" \
4639 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004640 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004641 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004642 : /*out*/ "=r" (_res) \
4643 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004644 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004645 ); \
4646 lval = (__typeof__(lval)) _res; \
4647 } while (0)
4648
4649#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
4650 do { \
4651 volatile OrigFn _orig = (orig); \
4652 volatile unsigned long _argvec[6]; \
4653 volatile unsigned long _res; \
4654 _argvec[0] = (unsigned long)_orig.nraddr; \
4655 _argvec[1] = (unsigned long)(arg1); \
4656 _argvec[2] = (unsigned long)(arg2); \
4657 _argvec[3] = (unsigned long)(arg3); \
4658 _argvec[4] = (unsigned long)(arg4); \
4659 _argvec[5] = (unsigned long)(arg5); \
4660 __asm__ volatile( \
4661 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004662 "sw $28, 0($29) \n\t" \
4663 "sw $31, 4($29) \n\t" \
4664 "lw $4, 20(%1) \n\t" \
4665 "subu $29, $29, 24\n\t" \
4666 "sw $4, 16($29) \n\t" \
4667 "lw $4, 4(%1) \n\t" \
4668 "lw $5, 8(%1) \n\t" \
4669 "lw $6, 12(%1) \n\t" \
4670 "lw $7, 16(%1) \n\t" \
4671 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004672 VALGRIND_CALL_NOREDIR_T9 \
4673 "addu $29, $29, 24 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004674 "lw $28, 0($29) \n\t" \
4675 "lw $31, 4($29) \n\t" \
4676 "addu $29, $29, 8 \n\t" \
4677 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004678 : /*out*/ "=r" (_res) \
4679 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004680 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004681 ); \
4682 lval = (__typeof__(lval)) _res; \
4683 } while (0)
4684#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
4685 do { \
4686 volatile OrigFn _orig = (orig); \
4687 volatile unsigned long _argvec[7]; \
4688 volatile unsigned long _res; \
4689 _argvec[0] = (unsigned long)_orig.nraddr; \
4690 _argvec[1] = (unsigned long)(arg1); \
4691 _argvec[2] = (unsigned long)(arg2); \
4692 _argvec[3] = (unsigned long)(arg3); \
4693 _argvec[4] = (unsigned long)(arg4); \
4694 _argvec[5] = (unsigned long)(arg5); \
4695 _argvec[6] = (unsigned long)(arg6); \
4696 __asm__ volatile( \
4697 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004698 "sw $28, 0($29) \n\t" \
4699 "sw $31, 4($29) \n\t" \
4700 "lw $4, 20(%1) \n\t" \
4701 "subu $29, $29, 32\n\t" \
4702 "sw $4, 16($29) \n\t" \
4703 "lw $4, 24(%1) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004704 "nop\n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004705 "sw $4, 20($29) \n\t" \
4706 "lw $4, 4(%1) \n\t" \
4707 "lw $5, 8(%1) \n\t" \
4708 "lw $6, 12(%1) \n\t" \
4709 "lw $7, 16(%1) \n\t" \
4710 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004711 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00004712 "addu $29, $29, 32 \n\t" \
4713 "lw $28, 0($29) \n\t" \
4714 "lw $31, 4($29) \n\t" \
4715 "addu $29, $29, 8 \n\t" \
4716 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004717 : /*out*/ "=r" (_res) \
4718 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004719 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004720 ); \
4721 lval = (__typeof__(lval)) _res; \
4722 } while (0)
4723
4724#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4725 arg7) \
4726 do { \
4727 volatile OrigFn _orig = (orig); \
4728 volatile unsigned long _argvec[8]; \
4729 volatile unsigned long _res; \
4730 _argvec[0] = (unsigned long)_orig.nraddr; \
4731 _argvec[1] = (unsigned long)(arg1); \
4732 _argvec[2] = (unsigned long)(arg2); \
4733 _argvec[3] = (unsigned long)(arg3); \
4734 _argvec[4] = (unsigned long)(arg4); \
4735 _argvec[5] = (unsigned long)(arg5); \
4736 _argvec[6] = (unsigned long)(arg6); \
4737 _argvec[7] = (unsigned long)(arg7); \
4738 __asm__ volatile( \
4739 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004740 "sw $28, 0($29) \n\t" \
4741 "sw $31, 4($29) \n\t" \
4742 "lw $4, 20(%1) \n\t" \
4743 "subu $29, $29, 32\n\t" \
4744 "sw $4, 16($29) \n\t" \
4745 "lw $4, 24(%1) \n\t" \
4746 "sw $4, 20($29) \n\t" \
4747 "lw $4, 28(%1) \n\t" \
4748 "sw $4, 24($29) \n\t" \
4749 "lw $4, 4(%1) \n\t" \
4750 "lw $5, 8(%1) \n\t" \
4751 "lw $6, 12(%1) \n\t" \
4752 "lw $7, 16(%1) \n\t" \
4753 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004754 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00004755 "addu $29, $29, 32 \n\t" \
4756 "lw $28, 0($29) \n\t" \
4757 "lw $31, 4($29) \n\t" \
4758 "addu $29, $29, 8 \n\t" \
4759 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004760 : /*out*/ "=r" (_res) \
4761 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004762 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004763 ); \
4764 lval = (__typeof__(lval)) _res; \
4765 } while (0)
4766
4767#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4768 arg7,arg8) \
4769 do { \
4770 volatile OrigFn _orig = (orig); \
4771 volatile unsigned long _argvec[9]; \
4772 volatile unsigned long _res; \
4773 _argvec[0] = (unsigned long)_orig.nraddr; \
4774 _argvec[1] = (unsigned long)(arg1); \
4775 _argvec[2] = (unsigned long)(arg2); \
4776 _argvec[3] = (unsigned long)(arg3); \
4777 _argvec[4] = (unsigned long)(arg4); \
4778 _argvec[5] = (unsigned long)(arg5); \
4779 _argvec[6] = (unsigned long)(arg6); \
4780 _argvec[7] = (unsigned long)(arg7); \
4781 _argvec[8] = (unsigned long)(arg8); \
4782 __asm__ volatile( \
4783 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004784 "sw $28, 0($29) \n\t" \
4785 "sw $31, 4($29) \n\t" \
4786 "lw $4, 20(%1) \n\t" \
4787 "subu $29, $29, 40\n\t" \
4788 "sw $4, 16($29) \n\t" \
4789 "lw $4, 24(%1) \n\t" \
4790 "sw $4, 20($29) \n\t" \
4791 "lw $4, 28(%1) \n\t" \
4792 "sw $4, 24($29) \n\t" \
4793 "lw $4, 32(%1) \n\t" \
4794 "sw $4, 28($29) \n\t" \
4795 "lw $4, 4(%1) \n\t" \
4796 "lw $5, 8(%1) \n\t" \
4797 "lw $6, 12(%1) \n\t" \
4798 "lw $7, 16(%1) \n\t" \
4799 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004800 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00004801 "addu $29, $29, 40 \n\t" \
4802 "lw $28, 0($29) \n\t" \
4803 "lw $31, 4($29) \n\t" \
4804 "addu $29, $29, 8 \n\t" \
4805 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004806 : /*out*/ "=r" (_res) \
4807 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004808 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004809 ); \
4810 lval = (__typeof__(lval)) _res; \
4811 } while (0)
4812
4813#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4814 arg7,arg8,arg9) \
4815 do { \
4816 volatile OrigFn _orig = (orig); \
4817 volatile unsigned long _argvec[10]; \
4818 volatile unsigned long _res; \
4819 _argvec[0] = (unsigned long)_orig.nraddr; \
4820 _argvec[1] = (unsigned long)(arg1); \
4821 _argvec[2] = (unsigned long)(arg2); \
4822 _argvec[3] = (unsigned long)(arg3); \
4823 _argvec[4] = (unsigned long)(arg4); \
4824 _argvec[5] = (unsigned long)(arg5); \
4825 _argvec[6] = (unsigned long)(arg6); \
4826 _argvec[7] = (unsigned long)(arg7); \
4827 _argvec[8] = (unsigned long)(arg8); \
4828 _argvec[9] = (unsigned long)(arg9); \
4829 __asm__ volatile( \
4830 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004831 "sw $28, 0($29) \n\t" \
4832 "sw $31, 4($29) \n\t" \
4833 "lw $4, 20(%1) \n\t" \
4834 "subu $29, $29, 40\n\t" \
4835 "sw $4, 16($29) \n\t" \
4836 "lw $4, 24(%1) \n\t" \
4837 "sw $4, 20($29) \n\t" \
4838 "lw $4, 28(%1) \n\t" \
4839 "sw $4, 24($29) \n\t" \
4840 "lw $4, 32(%1) \n\t" \
4841 "sw $4, 28($29) \n\t" \
4842 "lw $4, 36(%1) \n\t" \
4843 "sw $4, 32($29) \n\t" \
4844 "lw $4, 4(%1) \n\t" \
4845 "lw $5, 8(%1) \n\t" \
4846 "lw $6, 12(%1) \n\t" \
4847 "lw $7, 16(%1) \n\t" \
4848 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004849 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00004850 "addu $29, $29, 40 \n\t" \
4851 "lw $28, 0($29) \n\t" \
4852 "lw $31, 4($29) \n\t" \
4853 "addu $29, $29, 8 \n\t" \
4854 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004855 : /*out*/ "=r" (_res) \
4856 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004857 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004858 ); \
4859 lval = (__typeof__(lval)) _res; \
4860 } while (0)
4861
4862#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4863 arg7,arg8,arg9,arg10) \
4864 do { \
4865 volatile OrigFn _orig = (orig); \
4866 volatile unsigned long _argvec[11]; \
4867 volatile unsigned long _res; \
4868 _argvec[0] = (unsigned long)_orig.nraddr; \
4869 _argvec[1] = (unsigned long)(arg1); \
4870 _argvec[2] = (unsigned long)(arg2); \
4871 _argvec[3] = (unsigned long)(arg3); \
4872 _argvec[4] = (unsigned long)(arg4); \
4873 _argvec[5] = (unsigned long)(arg5); \
4874 _argvec[6] = (unsigned long)(arg6); \
4875 _argvec[7] = (unsigned long)(arg7); \
4876 _argvec[8] = (unsigned long)(arg8); \
4877 _argvec[9] = (unsigned long)(arg9); \
4878 _argvec[10] = (unsigned long)(arg10); \
4879 __asm__ volatile( \
4880 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004881 "sw $28, 0($29) \n\t" \
4882 "sw $31, 4($29) \n\t" \
4883 "lw $4, 20(%1) \n\t" \
4884 "subu $29, $29, 48\n\t" \
4885 "sw $4, 16($29) \n\t" \
4886 "lw $4, 24(%1) \n\t" \
4887 "sw $4, 20($29) \n\t" \
4888 "lw $4, 28(%1) \n\t" \
4889 "sw $4, 24($29) \n\t" \
4890 "lw $4, 32(%1) \n\t" \
4891 "sw $4, 28($29) \n\t" \
4892 "lw $4, 36(%1) \n\t" \
4893 "sw $4, 32($29) \n\t" \
4894 "lw $4, 40(%1) \n\t" \
4895 "sw $4, 36($29) \n\t" \
4896 "lw $4, 4(%1) \n\t" \
4897 "lw $5, 8(%1) \n\t" \
4898 "lw $6, 12(%1) \n\t" \
4899 "lw $7, 16(%1) \n\t" \
4900 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004901 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00004902 "addu $29, $29, 48 \n\t" \
4903 "lw $28, 0($29) \n\t" \
4904 "lw $31, 4($29) \n\t" \
4905 "addu $29, $29, 8 \n\t" \
4906 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004907 : /*out*/ "=r" (_res) \
4908 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004909 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004910 ); \
4911 lval = (__typeof__(lval)) _res; \
4912 } while (0)
4913
4914#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
4915 arg6,arg7,arg8,arg9,arg10, \
4916 arg11) \
4917 do { \
4918 volatile OrigFn _orig = (orig); \
4919 volatile unsigned long _argvec[12]; \
4920 volatile unsigned long _res; \
4921 _argvec[0] = (unsigned long)_orig.nraddr; \
4922 _argvec[1] = (unsigned long)(arg1); \
4923 _argvec[2] = (unsigned long)(arg2); \
4924 _argvec[3] = (unsigned long)(arg3); \
4925 _argvec[4] = (unsigned long)(arg4); \
4926 _argvec[5] = (unsigned long)(arg5); \
4927 _argvec[6] = (unsigned long)(arg6); \
4928 _argvec[7] = (unsigned long)(arg7); \
4929 _argvec[8] = (unsigned long)(arg8); \
4930 _argvec[9] = (unsigned long)(arg9); \
4931 _argvec[10] = (unsigned long)(arg10); \
4932 _argvec[11] = (unsigned long)(arg11); \
4933 __asm__ volatile( \
4934 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004935 "sw $28, 0($29) \n\t" \
4936 "sw $31, 4($29) \n\t" \
4937 "lw $4, 20(%1) \n\t" \
4938 "subu $29, $29, 48\n\t" \
4939 "sw $4, 16($29) \n\t" \
4940 "lw $4, 24(%1) \n\t" \
4941 "sw $4, 20($29) \n\t" \
4942 "lw $4, 28(%1) \n\t" \
4943 "sw $4, 24($29) \n\t" \
4944 "lw $4, 32(%1) \n\t" \
4945 "sw $4, 28($29) \n\t" \
4946 "lw $4, 36(%1) \n\t" \
4947 "sw $4, 32($29) \n\t" \
4948 "lw $4, 40(%1) \n\t" \
4949 "sw $4, 36($29) \n\t" \
4950 "lw $4, 44(%1) \n\t" \
4951 "sw $4, 40($29) \n\t" \
4952 "lw $4, 4(%1) \n\t" \
4953 "lw $5, 8(%1) \n\t" \
4954 "lw $6, 12(%1) \n\t" \
4955 "lw $7, 16(%1) \n\t" \
4956 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004957 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00004958 "addu $29, $29, 48 \n\t" \
4959 "lw $28, 0($29) \n\t" \
4960 "lw $31, 4($29) \n\t" \
4961 "addu $29, $29, 8 \n\t" \
4962 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004963 : /*out*/ "=r" (_res) \
4964 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004965 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004966 ); \
4967 lval = (__typeof__(lval)) _res; \
4968 } while (0)
4969
4970#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
4971 arg6,arg7,arg8,arg9,arg10, \
4972 arg11,arg12) \
4973 do { \
4974 volatile OrigFn _orig = (orig); \
4975 volatile unsigned long _argvec[13]; \
4976 volatile unsigned long _res; \
4977 _argvec[0] = (unsigned long)_orig.nraddr; \
4978 _argvec[1] = (unsigned long)(arg1); \
4979 _argvec[2] = (unsigned long)(arg2); \
4980 _argvec[3] = (unsigned long)(arg3); \
4981 _argvec[4] = (unsigned long)(arg4); \
4982 _argvec[5] = (unsigned long)(arg5); \
4983 _argvec[6] = (unsigned long)(arg6); \
4984 _argvec[7] = (unsigned long)(arg7); \
4985 _argvec[8] = (unsigned long)(arg8); \
4986 _argvec[9] = (unsigned long)(arg9); \
4987 _argvec[10] = (unsigned long)(arg10); \
4988 _argvec[11] = (unsigned long)(arg11); \
4989 _argvec[12] = (unsigned long)(arg12); \
4990 __asm__ volatile( \
4991 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004992 "sw $28, 0($29) \n\t" \
4993 "sw $31, 4($29) \n\t" \
4994 "lw $4, 20(%1) \n\t" \
4995 "subu $29, $29, 56\n\t" \
4996 "sw $4, 16($29) \n\t" \
4997 "lw $4, 24(%1) \n\t" \
4998 "sw $4, 20($29) \n\t" \
4999 "lw $4, 28(%1) \n\t" \
5000 "sw $4, 24($29) \n\t" \
5001 "lw $4, 32(%1) \n\t" \
5002 "sw $4, 28($29) \n\t" \
5003 "lw $4, 36(%1) \n\t" \
5004 "sw $4, 32($29) \n\t" \
5005 "lw $4, 40(%1) \n\t" \
5006 "sw $4, 36($29) \n\t" \
5007 "lw $4, 44(%1) \n\t" \
5008 "sw $4, 40($29) \n\t" \
5009 "lw $4, 48(%1) \n\t" \
5010 "sw $4, 44($29) \n\t" \
5011 "lw $4, 4(%1) \n\t" \
5012 "lw $5, 8(%1) \n\t" \
5013 "lw $6, 12(%1) \n\t" \
5014 "lw $7, 16(%1) \n\t" \
5015 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005016 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00005017 "addu $29, $29, 56 \n\t" \
5018 "lw $28, 0($29) \n\t" \
5019 "lw $31, 4($29) \n\t" \
5020 "addu $29, $29, 8 \n\t" \
5021 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005022 : /*out*/ "=r" (_res) \
petarj4df0bfc2013-02-27 23:17:33 +00005023 : /*in*/ "r" (&_argvec[0]) \
5024 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005025 ); \
5026 lval = (__typeof__(lval)) _res; \
5027 } while (0)
5028
5029#endif /* PLAT_mips32_linux */
5030
petarj4df0bfc2013-02-27 23:17:33 +00005031/* ------------------------- mips64-linux ------------------------- */
5032
5033#if defined(PLAT_mips64_linux)
5034
5035/* These regs are trashed by the hidden call. */
5036#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \
5037"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
5038"$25", "$31"
5039
5040/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
5041 long) == 4. */
5042
5043#define CALL_FN_W_v(lval, orig) \
5044 do { \
5045 volatile OrigFn _orig = (orig); \
5046 volatile unsigned long _argvec[1]; \
5047 volatile unsigned long _res; \
5048 _argvec[0] = (unsigned long)_orig.nraddr; \
5049 __asm__ volatile( \
5050 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5051 VALGRIND_CALL_NOREDIR_T9 \
5052 "move %0, $2\n" \
5053 : /*out*/ "=r" (_res) \
5054 : /*in*/ "0" (&_argvec[0]) \
5055 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5056 ); \
5057 lval = (__typeof__(lval)) _res; \
5058 } while (0)
5059
5060#define CALL_FN_W_W(lval, orig, arg1) \
5061 do { \
5062 volatile OrigFn _orig = (orig); \
5063 volatile unsigned long _argvec[2]; \
5064 volatile unsigned long _res; \
5065 _argvec[0] = (unsigned long)_orig.nraddr; \
5066 _argvec[1] = (unsigned long)(arg1); \
5067 __asm__ volatile( \
5068 "ld $4, 8(%1)\n\t" /* arg1*/ \
5069 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5070 VALGRIND_CALL_NOREDIR_T9 \
5071 "move %0, $2\n" \
5072 : /*out*/ "=r" (_res) \
5073 : /*in*/ "r" (&_argvec[0]) \
5074 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5075 ); \
5076 lval = (__typeof__(lval)) _res; \
5077 } while (0)
5078
5079#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
5080 do { \
5081 volatile OrigFn _orig = (orig); \
5082 volatile unsigned long _argvec[3]; \
5083 volatile unsigned long _res; \
5084 _argvec[0] = (unsigned long)_orig.nraddr; \
5085 _argvec[1] = (unsigned long)(arg1); \
5086 _argvec[2] = (unsigned long)(arg2); \
5087 __asm__ volatile( \
5088 "ld $4, 8(%1)\n\t" \
5089 "ld $5, 16(%1)\n\t" \
5090 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5091 VALGRIND_CALL_NOREDIR_T9 \
5092 "move %0, $2\n" \
5093 : /*out*/ "=r" (_res) \
5094 : /*in*/ "r" (&_argvec[0]) \
5095 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5096 ); \
5097 lval = (__typeof__(lval)) _res; \
5098 } while (0)
5099
5100#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
5101 do { \
5102 volatile OrigFn _orig = (orig); \
5103 volatile unsigned long _argvec[4]; \
5104 volatile unsigned long _res; \
5105 _argvec[0] = (unsigned long)_orig.nraddr; \
5106 _argvec[1] = (unsigned long)(arg1); \
5107 _argvec[2] = (unsigned long)(arg2); \
5108 _argvec[3] = (unsigned long)(arg3); \
5109 __asm__ volatile( \
5110 "ld $4, 8(%1)\n\t" \
5111 "ld $5, 16(%1)\n\t" \
5112 "ld $6, 24(%1)\n\t" \
5113 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5114 VALGRIND_CALL_NOREDIR_T9 \
5115 "move %0, $2\n" \
5116 : /*out*/ "=r" (_res) \
5117 : /*in*/ "r" (&_argvec[0]) \
5118 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5119 ); \
5120 lval = (__typeof__(lval)) _res; \
5121 } while (0)
5122
5123#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
5124 do { \
5125 volatile OrigFn _orig = (orig); \
5126 volatile unsigned long _argvec[5]; \
5127 volatile unsigned long _res; \
5128 _argvec[0] = (unsigned long)_orig.nraddr; \
5129 _argvec[1] = (unsigned long)(arg1); \
5130 _argvec[2] = (unsigned long)(arg2); \
5131 _argvec[3] = (unsigned long)(arg3); \
5132 _argvec[4] = (unsigned long)(arg4); \
5133 __asm__ volatile( \
5134 "ld $4, 8(%1)\n\t" \
5135 "ld $5, 16(%1)\n\t" \
5136 "ld $6, 24(%1)\n\t" \
5137 "ld $7, 32(%1)\n\t" \
5138 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5139 VALGRIND_CALL_NOREDIR_T9 \
5140 "move %0, $2\n" \
5141 : /*out*/ "=r" (_res) \
5142 : /*in*/ "r" (&_argvec[0]) \
5143 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5144 ); \
5145 lval = (__typeof__(lval)) _res; \
5146 } while (0)
5147
5148#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
5149 do { \
5150 volatile OrigFn _orig = (orig); \
5151 volatile unsigned long _argvec[6]; \
5152 volatile unsigned long _res; \
5153 _argvec[0] = (unsigned long)_orig.nraddr; \
5154 _argvec[1] = (unsigned long)(arg1); \
5155 _argvec[2] = (unsigned long)(arg2); \
5156 _argvec[3] = (unsigned long)(arg3); \
5157 _argvec[4] = (unsigned long)(arg4); \
5158 _argvec[5] = (unsigned long)(arg5); \
5159 __asm__ volatile( \
5160 "ld $4, 8(%1)\n\t" \
5161 "ld $5, 16(%1)\n\t" \
5162 "ld $6, 24(%1)\n\t" \
5163 "ld $7, 32(%1)\n\t" \
5164 "ld $8, 40(%1)\n\t" \
5165 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5166 VALGRIND_CALL_NOREDIR_T9 \
5167 "move %0, $2\n" \
5168 : /*out*/ "=r" (_res) \
5169 : /*in*/ "r" (&_argvec[0]) \
5170 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5171 ); \
5172 lval = (__typeof__(lval)) _res; \
5173 } while (0)
5174
5175#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
5176 do { \
5177 volatile OrigFn _orig = (orig); \
5178 volatile unsigned long _argvec[7]; \
5179 volatile unsigned long _res; \
5180 _argvec[0] = (unsigned long)_orig.nraddr; \
5181 _argvec[1] = (unsigned long)(arg1); \
5182 _argvec[2] = (unsigned long)(arg2); \
5183 _argvec[3] = (unsigned long)(arg3); \
5184 _argvec[4] = (unsigned long)(arg4); \
5185 _argvec[5] = (unsigned long)(arg5); \
5186 _argvec[6] = (unsigned long)(arg6); \
5187 __asm__ volatile( \
5188 "ld $4, 8(%1)\n\t" \
5189 "ld $5, 16(%1)\n\t" \
5190 "ld $6, 24(%1)\n\t" \
5191 "ld $7, 32(%1)\n\t" \
5192 "ld $8, 40(%1)\n\t" \
5193 "ld $9, 48(%1)\n\t" \
5194 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5195 VALGRIND_CALL_NOREDIR_T9 \
5196 "move %0, $2\n" \
5197 : /*out*/ "=r" (_res) \
5198 : /*in*/ "r" (&_argvec[0]) \
5199 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5200 ); \
5201 lval = (__typeof__(lval)) _res; \
5202 } while (0)
5203
5204#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5205 arg7) \
5206 do { \
5207 volatile OrigFn _orig = (orig); \
5208 volatile unsigned long _argvec[8]; \
5209 volatile unsigned long _res; \
5210 _argvec[0] = (unsigned long)_orig.nraddr; \
5211 _argvec[1] = (unsigned long)(arg1); \
5212 _argvec[2] = (unsigned long)(arg2); \
5213 _argvec[3] = (unsigned long)(arg3); \
5214 _argvec[4] = (unsigned long)(arg4); \
5215 _argvec[5] = (unsigned long)(arg5); \
5216 _argvec[6] = (unsigned long)(arg6); \
5217 _argvec[7] = (unsigned long)(arg7); \
5218 __asm__ volatile( \
5219 "ld $4, 8(%1)\n\t" \
5220 "ld $5, 16(%1)\n\t" \
5221 "ld $6, 24(%1)\n\t" \
5222 "ld $7, 32(%1)\n\t" \
5223 "ld $8, 40(%1)\n\t" \
5224 "ld $9, 48(%1)\n\t" \
5225 "ld $10, 56(%1)\n\t" \
5226 "ld $25, 0(%1) \n\t" /* target->t9 */ \
5227 VALGRIND_CALL_NOREDIR_T9 \
5228 "move %0, $2\n" \
5229 : /*out*/ "=r" (_res) \
5230 : /*in*/ "r" (&_argvec[0]) \
5231 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5232 ); \
5233 lval = (__typeof__(lval)) _res; \
5234 } while (0)
5235
5236#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5237 arg7,arg8) \
5238 do { \
5239 volatile OrigFn _orig = (orig); \
5240 volatile unsigned long _argvec[9]; \
5241 volatile unsigned long _res; \
5242 _argvec[0] = (unsigned long)_orig.nraddr; \
5243 _argvec[1] = (unsigned long)(arg1); \
5244 _argvec[2] = (unsigned long)(arg2); \
5245 _argvec[3] = (unsigned long)(arg3); \
5246 _argvec[4] = (unsigned long)(arg4); \
5247 _argvec[5] = (unsigned long)(arg5); \
5248 _argvec[6] = (unsigned long)(arg6); \
5249 _argvec[7] = (unsigned long)(arg7); \
5250 _argvec[8] = (unsigned long)(arg8); \
5251 __asm__ volatile( \
5252 "ld $4, 8(%1)\n\t" \
5253 "ld $5, 16(%1)\n\t" \
5254 "ld $6, 24(%1)\n\t" \
5255 "ld $7, 32(%1)\n\t" \
5256 "ld $8, 40(%1)\n\t" \
5257 "ld $9, 48(%1)\n\t" \
5258 "ld $10, 56(%1)\n\t" \
5259 "ld $11, 64(%1)\n\t" \
5260 "ld $25, 0(%1) \n\t" /* target->t9 */ \
5261 VALGRIND_CALL_NOREDIR_T9 \
5262 "move %0, $2\n" \
5263 : /*out*/ "=r" (_res) \
5264 : /*in*/ "r" (&_argvec[0]) \
5265 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5266 ); \
5267 lval = (__typeof__(lval)) _res; \
5268 } while (0)
5269
5270#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5271 arg7,arg8,arg9) \
5272 do { \
5273 volatile OrigFn _orig = (orig); \
5274 volatile unsigned long _argvec[10]; \
5275 volatile unsigned long _res; \
5276 _argvec[0] = (unsigned long)_orig.nraddr; \
5277 _argvec[1] = (unsigned long)(arg1); \
5278 _argvec[2] = (unsigned long)(arg2); \
5279 _argvec[3] = (unsigned long)(arg3); \
5280 _argvec[4] = (unsigned long)(arg4); \
5281 _argvec[5] = (unsigned long)(arg5); \
5282 _argvec[6] = (unsigned long)(arg6); \
5283 _argvec[7] = (unsigned long)(arg7); \
5284 _argvec[8] = (unsigned long)(arg8); \
5285 _argvec[9] = (unsigned long)(arg9); \
5286 __asm__ volatile( \
5287 "dsubu $29, $29, 8\n\t" \
5288 "ld $4, 72(%1)\n\t" \
5289 "sd $4, 0($29)\n\t" \
5290 "ld $4, 8(%1)\n\t" \
5291 "ld $5, 16(%1)\n\t" \
5292 "ld $6, 24(%1)\n\t" \
5293 "ld $7, 32(%1)\n\t" \
5294 "ld $8, 40(%1)\n\t" \
5295 "ld $9, 48(%1)\n\t" \
5296 "ld $10, 56(%1)\n\t" \
5297 "ld $11, 64(%1)\n\t" \
5298 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5299 VALGRIND_CALL_NOREDIR_T9 \
5300 "daddu $29, $29, 8\n\t" \
5301 "move %0, $2\n" \
5302 : /*out*/ "=r" (_res) \
5303 : /*in*/ "r" (&_argvec[0]) \
5304 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5305 ); \
5306 lval = (__typeof__(lval)) _res; \
5307 } while (0)
5308
5309#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5310 arg7,arg8,arg9,arg10) \
5311 do { \
5312 volatile OrigFn _orig = (orig); \
5313 volatile unsigned long _argvec[11]; \
5314 volatile unsigned long _res; \
5315 _argvec[0] = (unsigned long)_orig.nraddr; \
5316 _argvec[1] = (unsigned long)(arg1); \
5317 _argvec[2] = (unsigned long)(arg2); \
5318 _argvec[3] = (unsigned long)(arg3); \
5319 _argvec[4] = (unsigned long)(arg4); \
5320 _argvec[5] = (unsigned long)(arg5); \
5321 _argvec[6] = (unsigned long)(arg6); \
5322 _argvec[7] = (unsigned long)(arg7); \
5323 _argvec[8] = (unsigned long)(arg8); \
5324 _argvec[9] = (unsigned long)(arg9); \
5325 _argvec[10] = (unsigned long)(arg10); \
5326 __asm__ volatile( \
5327 "dsubu $29, $29, 16\n\t" \
5328 "ld $4, 72(%1)\n\t" \
5329 "sd $4, 0($29)\n\t" \
5330 "ld $4, 80(%1)\n\t" \
5331 "sd $4, 8($29)\n\t" \
5332 "ld $4, 8(%1)\n\t" \
5333 "ld $5, 16(%1)\n\t" \
5334 "ld $6, 24(%1)\n\t" \
5335 "ld $7, 32(%1)\n\t" \
5336 "ld $8, 40(%1)\n\t" \
5337 "ld $9, 48(%1)\n\t" \
5338 "ld $10, 56(%1)\n\t" \
5339 "ld $11, 64(%1)\n\t" \
5340 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5341 VALGRIND_CALL_NOREDIR_T9 \
5342 "daddu $29, $29, 16\n\t" \
5343 "move %0, $2\n" \
5344 : /*out*/ "=r" (_res) \
5345 : /*in*/ "r" (&_argvec[0]) \
5346 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5347 ); \
5348 lval = (__typeof__(lval)) _res; \
5349 } while (0)
5350
5351#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
5352 arg6,arg7,arg8,arg9,arg10, \
5353 arg11) \
5354 do { \
5355 volatile OrigFn _orig = (orig); \
5356 volatile unsigned long _argvec[12]; \
5357 volatile unsigned long _res; \
5358 _argvec[0] = (unsigned long)_orig.nraddr; \
5359 _argvec[1] = (unsigned long)(arg1); \
5360 _argvec[2] = (unsigned long)(arg2); \
5361 _argvec[3] = (unsigned long)(arg3); \
5362 _argvec[4] = (unsigned long)(arg4); \
5363 _argvec[5] = (unsigned long)(arg5); \
5364 _argvec[6] = (unsigned long)(arg6); \
5365 _argvec[7] = (unsigned long)(arg7); \
5366 _argvec[8] = (unsigned long)(arg8); \
5367 _argvec[9] = (unsigned long)(arg9); \
5368 _argvec[10] = (unsigned long)(arg10); \
5369 _argvec[11] = (unsigned long)(arg11); \
5370 __asm__ volatile( \
5371 "dsubu $29, $29, 24\n\t" \
5372 "ld $4, 72(%1)\n\t" \
5373 "sd $4, 0($29)\n\t" \
5374 "ld $4, 80(%1)\n\t" \
5375 "sd $4, 8($29)\n\t" \
5376 "ld $4, 88(%1)\n\t" \
5377 "sd $4, 16($29)\n\t" \
5378 "ld $4, 8(%1)\n\t" \
5379 "ld $5, 16(%1)\n\t" \
5380 "ld $6, 24(%1)\n\t" \
5381 "ld $7, 32(%1)\n\t" \
5382 "ld $8, 40(%1)\n\t" \
5383 "ld $9, 48(%1)\n\t" \
5384 "ld $10, 56(%1)\n\t" \
5385 "ld $11, 64(%1)\n\t" \
5386 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5387 VALGRIND_CALL_NOREDIR_T9 \
5388 "daddu $29, $29, 24\n\t" \
5389 "move %0, $2\n" \
5390 : /*out*/ "=r" (_res) \
5391 : /*in*/ "r" (&_argvec[0]) \
5392 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5393 ); \
5394 lval = (__typeof__(lval)) _res; \
5395 } while (0)
5396
5397#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
5398 arg6,arg7,arg8,arg9,arg10, \
5399 arg11,arg12) \
5400 do { \
5401 volatile OrigFn _orig = (orig); \
5402 volatile unsigned long _argvec[13]; \
5403 volatile unsigned long _res; \
5404 _argvec[0] = (unsigned long)_orig.nraddr; \
5405 _argvec[1] = (unsigned long)(arg1); \
5406 _argvec[2] = (unsigned long)(arg2); \
5407 _argvec[3] = (unsigned long)(arg3); \
5408 _argvec[4] = (unsigned long)(arg4); \
5409 _argvec[5] = (unsigned long)(arg5); \
5410 _argvec[6] = (unsigned long)(arg6); \
5411 _argvec[7] = (unsigned long)(arg7); \
5412 _argvec[8] = (unsigned long)(arg8); \
5413 _argvec[9] = (unsigned long)(arg9); \
5414 _argvec[10] = (unsigned long)(arg10); \
5415 _argvec[11] = (unsigned long)(arg11); \
5416 _argvec[12] = (unsigned long)(arg12); \
5417 __asm__ volatile( \
5418 "dsubu $29, $29, 32\n\t" \
5419 "ld $4, 72(%1)\n\t" \
5420 "sd $4, 0($29)\n\t" \
5421 "ld $4, 80(%1)\n\t" \
5422 "sd $4, 8($29)\n\t" \
5423 "ld $4, 88(%1)\n\t" \
5424 "sd $4, 16($29)\n\t" \
5425 "ld $4, 96(%1)\n\t" \
5426 "sd $4, 24($29)\n\t" \
5427 "ld $4, 8(%1)\n\t" \
5428 "ld $5, 16(%1)\n\t" \
5429 "ld $6, 24(%1)\n\t" \
5430 "ld $7, 32(%1)\n\t" \
5431 "ld $8, 40(%1)\n\t" \
5432 "ld $9, 48(%1)\n\t" \
5433 "ld $10, 56(%1)\n\t" \
5434 "ld $11, 64(%1)\n\t" \
5435 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5436 VALGRIND_CALL_NOREDIR_T9 \
5437 "daddu $29, $29, 32\n\t" \
5438 "move %0, $2\n" \
5439 : /*out*/ "=r" (_res) \
5440 : /*in*/ "r" (&_argvec[0]) \
5441 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5442 ); \
5443 lval = (__typeof__(lval)) _res; \
5444 } while (0)
5445
5446#endif /* PLAT_mips64_linux */
5447
sewardj0ec07f32006-01-12 12:32:32 +00005448
5449/* ------------------------------------------------------------------ */
5450/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
5451/* */
njn30d76c62005-06-18 15:07:39 +00005452/* ------------------------------------------------------------------ */
5453
sewardj2e93c502002-04-12 11:12:52 +00005454/* Some request codes. There are many more of these, but most are not
5455 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00005456 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00005457
sewardj0ec07f32006-01-12 12:32:32 +00005458 Core ones are in the range 0x00000000--0x0000ffff. The non-public
5459 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00005460*/
5461
sewardj0ec07f32006-01-12 12:32:32 +00005462/* These macros are used by tools -- they must be public, but don't
5463 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00005464#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00005465 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00005466#define VG_IS_TOOL_USERREQ(a, b, v) \
5467 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00005468
sewardj5ce4b152006-03-11 12:57:41 +00005469/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
5470 This enum comprises an ABI exported by Valgrind to programs
5471 which use client requests. DO NOT CHANGE THE ORDER OF THESE
5472 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00005473typedef
njn4c791212003-05-02 17:53:54 +00005474 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
5475 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00005476
sewardj0ec07f32006-01-12 12:32:32 +00005477 /* These allow any function to be called from the simulated
5478 CPU but run on the real CPU. Nb: the first arg passed to
5479 the function is always the ThreadId of the running
5480 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00005481 function, etc. */
njn4c791212003-05-02 17:53:54 +00005482 VG_USERREQ__CLIENT_CALL0 = 0x1101,
5483 VG_USERREQ__CLIENT_CALL1 = 0x1102,
5484 VG_USERREQ__CLIENT_CALL2 = 0x1103,
5485 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00005486
sewardj0ec07f32006-01-12 12:32:32 +00005487 /* Can be useful in regression testing suites -- eg. can
5488 send Valgrind's output to /dev/null and still count
5489 errors. */
njn4c791212003-05-02 17:53:54 +00005490 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00005491
philippe46207652013-01-20 17:11:58 +00005492 /* Allows the client program and/or gdbserver to execute a monitor
5493 command. */
sewardj3b290482011-05-06 21:02:55 +00005494 VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
5495
sewardj0ec07f32006-01-12 12:32:32 +00005496 /* These are useful and can be interpreted by any tool that
5497 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00005498 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
bart91347382011-03-25 20:07:25 +00005499 VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
njnd7994182003-10-02 13:44:04 +00005500 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00005501 /* Memory pool support. */
5502 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
5503 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
5504 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
5505 VG_USERREQ__MEMPOOL_FREE = 0x1306,
sewardj2c1c9df2006-07-28 00:06:37 +00005506 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
sewardjc740d762006-10-05 17:59:23 +00005507 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
5508 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
5509 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
njnd7994182003-10-02 13:44:04 +00005510
fitzhardinge39de4b42003-10-31 07:12:21 +00005511 /* Allow printfs to valgrind log. */
sewardjc560fb32010-01-28 15:23:54 +00005512 /* The first two pass the va_list argument by value, which
5513 assumes it is the same size as or smaller than a UWord,
5514 which generally isn't the case. Hence are deprecated.
5515 The second two pass the vargs by reference and so are
5516 immune to this problem. */
5517 /* both :: char* fmt, va_list vargs (DEPRECATED) */
njn30d76c62005-06-18 15:07:39 +00005518 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00005519 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
sewardjc560fb32010-01-28 15:23:54 +00005520 /* both :: char* fmt, va_list* vargs */
5521 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
5522 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
rjwalsh0140af52005-06-04 20:42:33 +00005523
5524 /* Stack support. */
5525 VG_USERREQ__STACK_REGISTER = 0x1501,
5526 VG_USERREQ__STACK_DEREGISTER = 0x1502,
sewardjc8259b82009-04-22 22:42:10 +00005527 VG_USERREQ__STACK_CHANGE = 0x1503,
5528
5529 /* Wine support */
sewardj5c659622010-08-20 18:22:07 +00005530 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
5531
5532 /* Querying of debug info. */
sewardjdc873c02011-07-24 16:02:33 +00005533 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
5534
5535 /* Disable/enable error reporting level. Takes a single
5536 Word arg which is the delta to this thread's error
5537 disablement indicator. Hence 1 disables or further
5538 disables errors, and -1 moves back towards enablement.
5539 Other values are not allowed. */
florianbb913cd2012-08-28 16:50:39 +00005540 VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801,
5541
5542 /* Initialise IR injection */
5543 VG_USERREQ__VEX_INIT_FOR_IRI = 0x1901
njn25e49d8e72002-09-23 09:36:25 +00005544 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00005545
sewardj0ec07f32006-01-12 12:32:32 +00005546#if !defined(__GNUC__)
5547# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00005548#endif
sewardj2e93c502002-04-12 11:12:52 +00005549
bartfa5115a2010-09-02 09:33:02 +00005550
sewardj0ec07f32006-01-12 12:32:32 +00005551/* Returns the number of Valgrinds this code is running under. That
5552 is, 0 if running natively, 1 if running under Valgrind, 2 if
5553 running under Valgrind which is running under another Valgrind,
5554 etc. */
bartfa5115a2010-09-02 09:33:02 +00005555#define RUNNING_ON_VALGRIND \
bart575ce8e2011-05-15 07:04:03 +00005556 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \
bartfa5115a2010-09-02 09:33:02 +00005557 VG_USERREQ__RUNNING_ON_VALGRIND, \
5558 0, 0, 0, 0, 0) \
sewardjde4a1d02002-03-22 01:27:54 +00005559
5560
sewardj18d75132002-05-16 11:06:21 +00005561/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
5562 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
5563 since it provides a way to make sure valgrind will retranslate the
5564 invalidated area. Returns no value. */
sewardj4b3a7422011-10-24 13:21:57 +00005565#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
5566 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DISCARD_TRANSLATIONS, \
5567 _qzz_addr, _qzz_len, 0, 0, 0)
sewardj18d75132002-05-16 11:06:21 +00005568
njn26aba4d2005-05-16 13:31:23 +00005569
sewardj0ec07f32006-01-12 12:32:32 +00005570/* These requests are for getting Valgrind itself to print something.
njnd55f0d92009-08-03 01:38:56 +00005571 Possibly with a backtrace. This is a really ugly hack. The return value
5572 is the number of characters printed, excluding the "**<pid>** " part at the
5573 start and the backtrace (if present). */
sewardj0ec07f32006-01-12 12:32:32 +00005574
bart42f83fe2012-01-31 10:13:51 +00005575#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00005576/* Modern GCC will optimize the static routine out if unused,
5577 and unused attribute will shut down warnings about it. */
5578static int VALGRIND_PRINTF(const char *format, ...)
5579 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00005580#endif
sewardj7eca0cc2006-04-12 17:15:35 +00005581static int
bart0da2c772010-09-01 10:18:36 +00005582#if defined(_MSC_VER)
5583__inline
5584#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00005585VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00005586{
bart8c7e25f2011-03-04 16:55:56 +00005587#if defined(NVALGRIND)
5588 return 0;
5589#else /* NVALGRIND */
bartaaaf21d2013-08-25 06:10:24 +00005590#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00005591 uintptr_t _qzz_res;
5592#else
njnc6168192004-11-29 13:54:10 +00005593 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00005594#endif
sewardjc560fb32010-01-28 15:23:54 +00005595 va_list vargs;
5596 va_start(vargs, format);
bartaaaf21d2013-08-25 06:10:24 +00005597#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00005598 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00005599 VG_USERREQ__PRINTF_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00005600 (uintptr_t)format,
5601 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00005602 0, 0, 0);
5603#else
bart575ce8e2011-05-15 07:04:03 +00005604 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00005605 VG_USERREQ__PRINTF_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00005606 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00005607 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00005608 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00005609#endif
sewardjc560fb32010-01-28 15:23:54 +00005610 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00005611 return (int)_qzz_res;
bart8c7e25f2011-03-04 16:55:56 +00005612#endif /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00005613}
5614
bart42f83fe2012-01-31 10:13:51 +00005615#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00005616static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
5617 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00005618#endif
sewardj7eca0cc2006-04-12 17:15:35 +00005619static int
bart0da2c772010-09-01 10:18:36 +00005620#if defined(_MSC_VER)
5621__inline
5622#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00005623VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00005624{
bart8c7e25f2011-03-04 16:55:56 +00005625#if defined(NVALGRIND)
5626 return 0;
5627#else /* NVALGRIND */
bartaaaf21d2013-08-25 06:10:24 +00005628#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00005629 uintptr_t _qzz_res;
5630#else
njnc6168192004-11-29 13:54:10 +00005631 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00005632#endif
sewardjc560fb32010-01-28 15:23:54 +00005633 va_list vargs;
5634 va_start(vargs, format);
bartaaaf21d2013-08-25 06:10:24 +00005635#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00005636 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00005637 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00005638 (uintptr_t)format,
5639 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00005640 0, 0, 0);
5641#else
bart575ce8e2011-05-15 07:04:03 +00005642 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00005643 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00005644 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00005645 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00005646 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00005647#endif
sewardjc560fb32010-01-28 15:23:54 +00005648 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00005649 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00005650#endif /* NVALGRIND */
bart8c7e25f2011-03-04 16:55:56 +00005651}
sewardj18d75132002-05-16 11:06:21 +00005652
sewardj0ec07f32006-01-12 12:32:32 +00005653
njn3e884182003-04-15 13:03:23 +00005654/* These requests allow control to move from the simulated CPU to the
njn1319b492006-11-20 22:02:40 +00005655 real CPU, calling an arbitary function.
5656
5657 Note that the current ThreadId is inserted as the first argument.
5658 So this call:
5659
5660 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
5661
5662 requires f to have this signature:
5663
5664 Word f(Word tid, Word arg1, Word arg2)
5665
5666 where "Word" is a word-sized type.
njn45fb4d32007-12-05 21:51:50 +00005667
5668 Note that these client requests are not entirely reliable. For example,
5669 if you call a function with them that subsequently calls printf(),
5670 there's a high chance Valgrind will crash. Generally, your prospects of
5671 these working are made higher if the called function does not refer to
5672 any global variables, and does not refer to any libc or other functions
5673 (printf et al). Any kind of entanglement with libc or dynamic linking is
5674 likely to have a bad outcome, for tricky reasons which we've grappled
5675 with a lot in the past.
njn1319b492006-11-20 22:02:40 +00005676*/
sewardj0ec07f32006-01-12 12:32:32 +00005677#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
bart575ce8e2011-05-15 07:04:03 +00005678 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
5679 VG_USERREQ__CLIENT_CALL0, \
5680 _qyy_fn, \
5681 0, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00005682
bart575ce8e2011-05-15 07:04:03 +00005683#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
5684 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
5685 VG_USERREQ__CLIENT_CALL1, \
5686 _qyy_fn, \
5687 _qyy_arg1, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00005688
bart575ce8e2011-05-15 07:04:03 +00005689#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
5690 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
5691 VG_USERREQ__CLIENT_CALL2, \
5692 _qyy_fn, \
5693 _qyy_arg1, _qyy_arg2, 0, 0)
njn3e884182003-04-15 13:03:23 +00005694
sewardj0ec07f32006-01-12 12:32:32 +00005695#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
bart575ce8e2011-05-15 07:04:03 +00005696 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
5697 VG_USERREQ__CLIENT_CALL3, \
5698 _qyy_fn, \
5699 _qyy_arg1, _qyy_arg2, \
5700 _qyy_arg3, 0)
njn3e884182003-04-15 13:03:23 +00005701
5702
nethercote7cc9c232004-01-21 15:08:04 +00005703/* Counts the number of errors that have been recorded by a tool. Nb:
5704 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00005705 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00005706#define VALGRIND_COUNT_ERRORS \
bart575ce8e2011-05-15 07:04:03 +00005707 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR( \
5708 0 /* default return */, \
sewardj0ec07f32006-01-12 12:32:32 +00005709 VG_USERREQ__COUNT_ERRORS, \
bart575ce8e2011-05-15 07:04:03 +00005710 0, 0, 0, 0, 0)
njn47363ab2003-04-21 13:24:40 +00005711
njn3ac96952009-07-09 23:35:44 +00005712/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
5713 when heap blocks are allocated in order to give accurate results. This
5714 happens automatically for the standard allocator functions such as
5715 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
5716 delete[], etc.
njnd7994182003-10-02 13:44:04 +00005717
njn3ac96952009-07-09 23:35:44 +00005718 But if your program uses a custom allocator, this doesn't automatically
5719 happen, and Valgrind will not do as well. For example, if you allocate
5720 superblocks with mmap() and then allocates chunks of the superblocks, all
5721 Valgrind's observations will be at the mmap() level and it won't know that
5722 the chunks should be considered separate entities. In Memcheck's case,
5723 that means you probably won't get heap block overrun detection (because
5724 there won't be redzones marked as unaddressable) and you definitely won't
5725 get any leak detection.
5726
5727 The following client requests allow a custom allocator to be annotated so
5728 that it can be handled accurately by Valgrind.
5729
5730 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
5731 by a malloc()-like function. For Memcheck (an illustrative case), this
5732 does two things:
5733
5734 - It records that the block has been allocated. This means any addresses
5735 within the block mentioned in error messages will be
5736 identified as belonging to the block. It also means that if the block
5737 isn't freed it will be detected by the leak checker.
5738
5739 - It marks the block as being addressable and undefined (if 'is_zeroed' is
5740 not set), or addressable and defined (if 'is_zeroed' is set). This
5741 controls how accesses to the block by the program are handled.
5742
5743 'addr' is the start of the usable block (ie. after any
5744 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
5745 can apply redzones -- these are blocks of padding at the start and end of
5746 each block. Adding redzones is recommended as it makes it much more likely
5747 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
5748 zeroed (or filled with another predictable value), as is the case for
5749 calloc().
5750
5751 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
5752 heap block -- that will be used by the client program -- is allocated.
5753 It's best to put it at the outermost level of the allocator if possible;
5754 for example, if you have a function my_alloc() which calls
5755 internal_alloc(), and the client request is put inside internal_alloc(),
5756 stack traces relating to the heap block will contain entries for both
5757 my_alloc() and internal_alloc(), which is probably not what you want.
5758
njnb965efb2009-08-10 07:36:54 +00005759 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
5760 custom blocks from within a heap block, B, that has been allocated with
5761 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
5762 -- the custom blocks will take precedence.
5763
njn3ac96952009-07-09 23:35:44 +00005764 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
5765 Memcheck, it does two things:
5766
5767 - It records that the block has been deallocated. This assumes that the
5768 block was annotated as having been allocated via
5769 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
5770
5771 - It marks the block as being unaddressable.
5772
5773 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
5774 heap block is deallocated.
5775
bart91347382011-03-25 20:07:25 +00005776 VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For
5777 Memcheck, it does four things:
5778
5779 - It records that the size of a block has been changed. This assumes that
5780 the block was annotated as having been allocated via
5781 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
5782
5783 - If the block shrunk, it marks the freed memory as being unaddressable.
5784
5785 - If the block grew, it marks the new area as undefined and defines a red
5786 zone past the end of the new block.
5787
5788 - The V-bits of the overlap between the old and the new block are preserved.
5789
5790 VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block
5791 and before deallocation of the old block.
5792
5793 In many cases, these three client requests will not be enough to get your
njn3ac96952009-07-09 23:35:44 +00005794 allocator working well with Memcheck. More specifically, if your allocator
5795 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
5796 will be necessary to mark the memory as addressable just before the zeroing
5797 occurs, otherwise you'll get a lot of invalid write errors. For example,
5798 you'll need to do this if your allocator recycles freed blocks, but it
5799 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
5800 Alternatively, if your allocator reuses freed blocks for allocator-internal
5801 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
5802
5803 Really, what's happening is a blurring of the lines between the client
5804 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
5805 memory should be considered unaddressable to the client program, but the
5806 allocator knows more than the rest of the client program and so may be able
5807 to safely access it. Extra client requests are necessary for Valgrind to
5808 understand the distinction between the allocator and the rest of the
5809 program.
5810
njn32f8d8c2009-07-15 02:31:45 +00005811 Ignored if addr == 0.
njn3ac96952009-07-09 23:35:44 +00005812*/
sewardj4b3a7422011-10-24 13:21:57 +00005813#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
5814 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MALLOCLIKE_BLOCK, \
5815 addr, sizeB, rzB, is_zeroed, 0)
njnd7994182003-10-02 13:44:04 +00005816
njn32f8d8c2009-07-15 02:31:45 +00005817/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
5818 Ignored if addr == 0.
5819*/
sewardj4b3a7422011-10-24 13:21:57 +00005820#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \
5821 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RESIZEINPLACE_BLOCK, \
5822 addr, oldSizeB, newSizeB, rzB, 0)
bart91347382011-03-25 20:07:25 +00005823
5824/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
5825 Ignored if addr == 0.
5826*/
sewardj4b3a7422011-10-24 13:21:57 +00005827#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
5828 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREELIKE_BLOCK, \
5829 addr, rzB, 0, 0, 0)
njnd7994182003-10-02 13:44:04 +00005830
rjwalshbc0bb832004-06-19 18:12:36 +00005831/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00005832#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
sewardj4b3a7422011-10-24 13:21:57 +00005833 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \
5834 pool, rzB, is_zeroed, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00005835
5836/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00005837#define VALGRIND_DESTROY_MEMPOOL(pool) \
sewardj4b3a7422011-10-24 13:21:57 +00005838 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DESTROY_MEMPOOL, \
5839 pool, 0, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00005840
5841/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00005842#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
sewardj4b3a7422011-10-24 13:21:57 +00005843 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_ALLOC, \
5844 pool, addr, size, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00005845
5846/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00005847#define VALGRIND_MEMPOOL_FREE(pool, addr) \
sewardj4b3a7422011-10-24 13:21:57 +00005848 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_FREE, \
5849 pool, addr, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00005850
sewardj2c1c9df2006-07-28 00:06:37 +00005851/* Disassociate any pieces outside a particular range. */
5852#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
sewardj4b3a7422011-10-24 13:21:57 +00005853 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_TRIM, \
5854 pool, addr, size, 0, 0)
sewardj2c1c9df2006-07-28 00:06:37 +00005855
sewardjc740d762006-10-05 17:59:23 +00005856/* Resize and/or move a piece associated with a memory pool. */
5857#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
sewardj4b3a7422011-10-24 13:21:57 +00005858 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MOVE_MEMPOOL, \
5859 poolA, poolB, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00005860
5861/* Resize and/or move a piece associated with a memory pool. */
5862#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
sewardj4b3a7422011-10-24 13:21:57 +00005863 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_CHANGE, \
5864 pool, addrA, addrB, size, 0)
sewardjc740d762006-10-05 17:59:23 +00005865
5866/* Return 1 if a mempool exists, else 0. */
5867#define VALGRIND_MEMPOOL_EXISTS(pool) \
bart575ce8e2011-05-15 07:04:03 +00005868 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardjc740d762006-10-05 17:59:23 +00005869 VG_USERREQ__MEMPOOL_EXISTS, \
bart575ce8e2011-05-15 07:04:03 +00005870 pool, 0, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00005871
rjwalsh0140af52005-06-04 20:42:33 +00005872/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00005873#define VALGRIND_STACK_REGISTER(start, end) \
bart575ce8e2011-05-15 07:04:03 +00005874 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00005875 VG_USERREQ__STACK_REGISTER, \
bart575ce8e2011-05-15 07:04:03 +00005876 start, end, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00005877
5878/* Unmark the piece of memory associated with a stack id as being a
5879 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00005880#define VALGRIND_STACK_DEREGISTER(id) \
sewardj4b3a7422011-10-24 13:21:57 +00005881 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_DEREGISTER, \
5882 id, 0, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00005883
5884/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00005885#define VALGRIND_STACK_CHANGE(id, start, end) \
sewardj4b3a7422011-10-24 13:21:57 +00005886 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_CHANGE, \
5887 id, start, end, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00005888
sewardjc8259b82009-04-22 22:42:10 +00005889/* Load PDB debug info for Wine PE image_map. */
sewardj4b3a7422011-10-24 13:21:57 +00005890#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
5891 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LOAD_PDB_DEBUGINFO, \
5892 fd, ptr, total_size, delta, 0)
sewardjc8259b82009-04-22 22:42:10 +00005893
sewardj5c659622010-08-20 18:22:07 +00005894/* Map a code address to a source file name and line number. buf64
5895 must point to a 64-byte buffer in the caller's address space. The
5896 result will be dumped in there and is guaranteed to be zero
5897 terminated. If no info is found, the first byte is set to zero. */
5898#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \
bart575ce8e2011-05-15 07:04:03 +00005899 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj5c659622010-08-20 18:22:07 +00005900 VG_USERREQ__MAP_IP_TO_SRCLOC, \
bart575ce8e2011-05-15 07:04:03 +00005901 addr, buf64, 0, 0, 0)
sewardj5c659622010-08-20 18:22:07 +00005902
sewardjdc873c02011-07-24 16:02:33 +00005903/* Disable error reporting for this thread. Behaves in a stack like
5904 way, so you can safely call this multiple times provided that
5905 VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times
5906 to re-enable reporting. The first call of this macro disables
5907 reporting. Subsequent calls have no effect except to increase the
5908 number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable
5909 reporting. Child threads do not inherit this setting from their
5910 parents -- they are always created with reporting enabled. */
bart06e9bf02011-10-07 09:39:56 +00005911#define VALGRIND_DISABLE_ERROR_REPORTING \
sewardj4b3a7422011-10-24 13:21:57 +00005912 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
5913 1, 0, 0, 0, 0)
sewardjdc873c02011-07-24 16:02:33 +00005914
5915/* Re-enable error reporting, as per comments on
5916 VALGRIND_DISABLE_ERROR_REPORTING. */
bart06e9bf02011-10-07 09:39:56 +00005917#define VALGRIND_ENABLE_ERROR_REPORTING \
sewardj4b3a7422011-10-24 13:21:57 +00005918 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
5919 -1, 0, 0, 0, 0)
sewardj0ec07f32006-01-12 12:32:32 +00005920
philippe46207652013-01-20 17:11:58 +00005921/* Execute a monitor command from the client program.
5922 If a connection is opened with GDB, the output will be sent
5923 according to the output mode set for vgdb.
5924 If no connection is opened, output will go to the log output.
5925 Returns 1 if command not recognised, 0 otherwise. */
5926#define VALGRIND_MONITOR_COMMAND(command) \
5927 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__GDB_MONITOR_COMMAND, \
5928 command, 0, 0, 0, 0)
5929
5930
sewardjc112c8e2011-06-24 18:26:11 +00005931#undef PLAT_x86_darwin
5932#undef PLAT_amd64_darwin
5933#undef PLAT_x86_win32
bartaaaf21d2013-08-25 06:10:24 +00005934#undef PLAT_amd64_win64
sewardjf5c1a7f2006-10-17 01:32:48 +00005935#undef PLAT_x86_linux
5936#undef PLAT_amd64_linux
5937#undef PLAT_ppc32_linux
5938#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +00005939#undef PLAT_arm_linux
sewardjb5b87402011-03-07 16:05:35 +00005940#undef PLAT_s390x_linux
sewardj5db15402012-06-07 09:13:21 +00005941#undef PLAT_mips32_linux
petarj4df0bfc2013-02-27 23:17:33 +00005942#undef PLAT_mips64_linux
sewardj0ec07f32006-01-12 12:32:32 +00005943
njn3e884182003-04-15 13:03:23 +00005944#endif /* __VALGRIND_H */