blob: 81c946a99cb2ceded55a03ab164bbac3b0479934 [file] [log] [blame]
sewardjb5f6f512005-03-10 23:59:00 +00001/* -*- c -*-
njn25e49d8e72002-09-23 09:36:25 +00002 ----------------------------------------------------------------
3
4 Notice that the following BSD-style license applies to this one
njn7fd15d62006-03-31 12:05:04 +00005 file (valgrind.h) only. The rest of Valgrind is licensed under the
6 terms of the GNU General Public License, version 2, unless
7 otherwise indicated. See the COPYING file in the source
8 distribution for details.
njn25e49d8e72002-09-23 09:36:25 +00009
10 ----------------------------------------------------------------
11
njnb9c427c2004-12-01 14:14:42 +000012 This file is part of Valgrind, a dynamic binary instrumentation
13 framework.
sewardjde4a1d02002-03-22 01:27:54 +000014
sewardj0f157dd2013-10-18 14:27:36 +000015 Copyright (C) 2000-2013 Julian Seward. All rights reserved.
sewardjde4a1d02002-03-22 01:27:54 +000016
njn25e49d8e72002-09-23 09:36:25 +000017 Redistribution and use in source and binary forms, with or without
18 modification, are permitted provided that the following conditions
19 are met:
sewardjde4a1d02002-03-22 01:27:54 +000020
njn25e49d8e72002-09-23 09:36:25 +000021 1. Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
sewardjde4a1d02002-03-22 01:27:54 +000023
njn25e49d8e72002-09-23 09:36:25 +000024 2. The origin of this software must not be misrepresented; you must
25 not claim that you wrote the original software. If you use this
26 software in a product, an acknowledgment in the product
27 documentation would be appreciated but is not required.
sewardjde4a1d02002-03-22 01:27:54 +000028
njn25e49d8e72002-09-23 09:36:25 +000029 3. Altered source versions must be plainly marked as such, and must
30 not be misrepresented as being the original software.
31
32 4. The name of the author may not be used to endorse or promote
33 products derived from this software without specific prior written
34 permission.
35
36 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
37 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
40 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
45 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47
48 ----------------------------------------------------------------
49
50 Notice that the above BSD-style license applies to this one file
51 (valgrind.h) only. The entire rest of Valgrind is licensed under
52 the terms of the GNU General Public License, version 2. See the
53 COPYING file in the source distribution for details.
54
55 ----------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +000056*/
57
58
njn30d76c62005-06-18 15:07:39 +000059/* This file is for inclusion into client (your!) code.
60
61 You can use these macros to manipulate and query Valgrind's
62 execution inside your own programs.
63
64 The resulting executables will still run without Valgrind, just a
65 little bit more slowly than they otherwise would, but otherwise
66 unchanged. When not running on valgrind, each client request
sewardj0ec07f32006-01-12 12:32:32 +000067 consumes very few (eg. 7) instructions, so the resulting performance
njn30d76c62005-06-18 15:07:39 +000068 loss is negligible unless you plan to execute client requests
69 millions of times per second. Nevertheless, if that is still a
70 problem, you can compile with the NVALGRIND symbol defined (gcc
71 -DNVALGRIND) so that client requests are not even compiled in. */
72
sewardjde4a1d02002-03-22 01:27:54 +000073#ifndef __VALGRIND_H
74#define __VALGRIND_H
75
sewardj71044162010-03-03 22:57:47 +000076
77/* ------------------------------------------------------------------ */
78/* VERSION NUMBER OF VALGRIND */
79/* ------------------------------------------------------------------ */
80
81/* Specify Valgrind's version number, so that user code can
sewardj0fe1d4c2010-04-19 08:43:26 +000082 conditionally compile based on our version number. Note that these
83 were introduced at version 3.6 and so do not exist in version 3.5
84 or earlier. The recommended way to use them to check for "version
85 X.Y or later" is (eg)
86
87#if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \
88 && (__VALGRIND_MAJOR__ > 3 \
89 || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6))
90*/
91#define __VALGRIND_MAJOR__ 3
sewardjbd830b42014-05-12 10:12:08 +000092#define __VALGRIND_MINOR__ 10
sewardj71044162010-03-03 22:57:47 +000093
94
fitzhardinge39de4b42003-10-31 07:12:21 +000095#include <stdarg.h>
96
njn3dd0a912005-06-28 19:44:10 +000097/* Nb: this file might be included in a file compiled with -ansi. So
98 we can't use C++ style "//" comments nor the "asm" keyword (instead
99 use "__asm__"). */
100
sewardjf5c1a7f2006-10-17 01:32:48 +0000101/* Derive some tags indicating what the target platform is. Note
sewardj0ec07f32006-01-12 12:32:32 +0000102 that in this file we're using the compiler's CPP symbols for
103 identifying architectures, which are different to the ones we use
104 within the rest of Valgrind. Note, __powerpc__ is active for both
105 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
sewardj59570ff2010-01-01 11:59:33 +0000106 latter (on Linux, that is).
107
108 Misc note: how to find out what's predefined in gcc by default:
109 gcc -Wp,-dM somefile.c
110*/
sewardj7af32302010-01-02 10:37:58 +0000111#undef PLAT_x86_darwin
112#undef PLAT_amd64_darwin
bart7f489812010-08-27 10:05:27 +0000113#undef PLAT_x86_win32
bartaaaf21d2013-08-25 06:10:24 +0000114#undef PLAT_amd64_win64
sewardjf5c1a7f2006-10-17 01:32:48 +0000115#undef PLAT_x86_linux
116#undef PLAT_amd64_linux
117#undef PLAT_ppc32_linux
carllcae0cc22014-08-07 23:17:29 +0000118#undef PLAT_ppc64be_linux
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
carllcae0cc22014-08-07 23:17:29 +0000143#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF != 2
144/* Big Endian uses ELF version 1 */
145# define PLAT_ppc64be_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000146#elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__)
sewardj59570ff2010-01-01 11:59:33 +0000147# define PLAT_arm_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000148#elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__)
149# define PLAT_arm64_linux 1
sewardjb5b87402011-03-07 16:05:35 +0000150#elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
151# define PLAT_s390x_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000152#elif defined(__linux__) && defined(__mips__) && (__mips==64)
petarj4df0bfc2013-02-27 23:17:33 +0000153# define PLAT_mips64_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000154#elif defined(__linux__) && defined(__mips__) && (__mips!=64)
sewardj5db15402012-06-07 09:13:21 +0000155# define PLAT_mips32_linux 1
njnf76d27a2009-05-28 01:53:07 +0000156#else
sewardjf5c1a7f2006-10-17 01:32:48 +0000157/* If we're not compiling for our target platform, don't generate
sewardj0ec07f32006-01-12 12:32:32 +0000158 any inline asms. */
sewardj0ec07f32006-01-12 12:32:32 +0000159# if !defined(NVALGRIND)
160# define NVALGRIND 1
161# endif
162#endif
163
164
njn30d76c62005-06-18 15:07:39 +0000165/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000166/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
167/* in here of use to end-users -- skip to the next section. */
njn30d76c62005-06-18 15:07:39 +0000168/* ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000169
bart575ce8e2011-05-15 07:04:03 +0000170/*
171 * VALGRIND_DO_CLIENT_REQUEST(): a statement that invokes a Valgrind client
172 * request. Accepts both pointers and integers as arguments.
173 *
sewardj4b3a7422011-10-24 13:21:57 +0000174 * VALGRIND_DO_CLIENT_REQUEST_STMT(): a statement that invokes a Valgrind
175 * client request that does not return a value.
176
bart575ce8e2011-05-15 07:04:03 +0000177 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
sewardj4b3a7422011-10-24 13:21:57 +0000178 * client request and whose value equals the client request result. Accepts
179 * both pointers and integers as arguments. Note that such calls are not
180 * necessarily pure functions -- they may have side effects.
bart575ce8e2011-05-15 07:04:03 +0000181 */
182
183#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, \
184 _zzq_request, _zzq_arg1, _zzq_arg2, \
185 _zzq_arg3, _zzq_arg4, _zzq_arg5) \
florian17dfe1a2011-10-22 15:04:05 +0000186 do { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default), \
bart575ce8e2011-05-15 07:04:03 +0000187 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
florian17dfe1a2011-10-22 15:04:05 +0000188 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
bart575ce8e2011-05-15 07:04:03 +0000189
sewardj4b3a7422011-10-24 13:21:57 +0000190#define VALGRIND_DO_CLIENT_REQUEST_STMT(_zzq_request, _zzq_arg1, \
191 _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
192 do { (void) VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
193 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
194 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
195
sewardj0ec07f32006-01-12 12:32:32 +0000196#if defined(NVALGRIND)
njn26aba4d2005-05-16 13:31:23 +0000197
198/* Define NVALGRIND to completely remove the Valgrind magic sequence
sewardj0ec07f32006-01-12 12:32:32 +0000199 from the compiled code (analogous to NDEBUG's effects on
200 assert()) */
bart575ce8e2011-05-15 07:04:03 +0000201#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
202 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000203 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000204 (_zzq_default)
njn26aba4d2005-05-16 13:31:23 +0000205
sewardj0ec07f32006-01-12 12:32:32 +0000206#else /* ! NVALGRIND */
nethercotee90c6832004-10-18 18:07:49 +0000207
sewardj0ec07f32006-01-12 12:32:32 +0000208/* The following defines the magic code sequences which the JITter
209 spots and handles magically. Don't look too closely at them as
210 they will rot your brain.
211
212 The assembly code sequences for all architectures is in this one
213 file. This is because this file must be stand-alone, and we don't
214 want to have multiple files.
215
216 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
217 value gets put in the return slot, so that everything works when
218 this is executed not under Valgrind. Args are passed in a memory
219 block, and so there's no intrinsic limit to the number that could
sewardj9af10a12006-02-01 14:59:42 +0000220 be passed, but it's currently five.
nethercotee90c6832004-10-18 18:07:49 +0000221
nethercote54265442004-10-26 12:56:58 +0000222 The macro args are:
223 _zzq_rlval result lvalue
224 _zzq_default default value (result returned when running on real CPU)
225 _zzq_request request code
sewardj9af10a12006-02-01 14:59:42 +0000226 _zzq_arg1..5 request params
nethercote54265442004-10-26 12:56:58 +0000227
sewardj0ec07f32006-01-12 12:32:32 +0000228 The other two macros are used to support function wrapping, and are
sewardjd68ac3e2006-01-20 14:31:57 +0000229 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
230 guest's NRADDR pseudo-register and whatever other information is
231 needed to safely run the call original from the wrapper: on
232 ppc64-linux, the R2 value at the divert point is also needed. This
233 information is abstracted into a user-visible type, OrigFn.
234
235 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
236 guest, but guarantees that the branch instruction will not be
237 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
238 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
239 complete inline asm, since it needs to be combined with more magic
240 inline asm stuff to be useful.
nethercotee90c6832004-10-18 18:07:49 +0000241*/
242
njnf76d27a2009-05-28 01:53:07 +0000243/* ------------------------- x86-{linux,darwin} ---------------- */
sewardjde4a4ab2005-03-23 13:10:32 +0000244
sewardj520a03a2010-10-07 10:46:15 +0000245#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
sewardj60227842010-10-07 10:00:56 +0000246 || (defined(PLAT_x86_win32) && defined(__GNUC__))
sewardjc8858442006-01-20 15:17:20 +0000247
248typedef
249 struct {
250 unsigned int nraddr; /* where's the code? */
251 }
252 OrigFn;
253
sewardj0ec07f32006-01-12 12:32:32 +0000254#define __SPECIAL_INSTRUCTION_PREAMBLE \
255 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000256 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000257
bart575ce8e2011-05-15 07:04:03 +0000258#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
259 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000260 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000261 __extension__ \
262 ({volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000263 volatile unsigned int _zzq_result; \
264 _zzq_args[0] = (unsigned int)(_zzq_request); \
265 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
266 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
267 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
268 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000269 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000270 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
271 /* %EDX = client_request ( %EAX ) */ \
272 "xchgl %%ebx,%%ebx" \
273 : "=d" (_zzq_result) \
274 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
275 : "cc", "memory" \
276 ); \
bart575ce8e2011-05-15 07:04:03 +0000277 _zzq_result; \
278 })
sewardj2c48c7b2005-11-29 13:05:56 +0000279
sewardjc8858442006-01-20 15:17:20 +0000280#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
281 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
282 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000283 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
284 /* %EAX = guest_NRADDR */ \
285 "xchgl %%ecx,%%ecx" \
286 : "=a" (__addr) \
287 : \
288 : "cc", "memory" \
289 ); \
sewardjc8858442006-01-20 15:17:20 +0000290 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000291 }
sewardj0ec07f32006-01-12 12:32:32 +0000292
293#define VALGRIND_CALL_NOREDIR_EAX \
294 __SPECIAL_INSTRUCTION_PREAMBLE \
295 /* call-noredir *%EAX */ \
296 "xchgl %%edx,%%edx\n\t"
florianbb913cd2012-08-28 16:50:39 +0000297
298#define VALGRIND_VEX_INJECT_IR() \
299 do { \
300 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
301 "xchgl %%edi,%%edi\n\t" \
302 : : : "cc", "memory" \
303 ); \
304 } while (0)
305
sewardj60227842010-10-07 10:00:56 +0000306#endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__) */
bart7f489812010-08-27 10:05:27 +0000307
308/* ------------------------- x86-Win32 ------------------------- */
309
310#if defined(PLAT_x86_win32) && !defined(__GNUC__)
311
312typedef
313 struct {
314 unsigned int nraddr; /* where's the code? */
315 }
316 OrigFn;
317
318#if defined(_MSC_VER)
319
320#define __SPECIAL_INSTRUCTION_PREAMBLE \
321 __asm rol edi, 3 __asm rol edi, 13 \
322 __asm rol edi, 29 __asm rol edi, 19
323
bart575ce8e2011-05-15 07:04:03 +0000324#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
325 _zzq_default, _zzq_request, \
bart7f489812010-08-27 10:05:27 +0000326 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000327 valgrind_do_client_request_expr((uintptr_t)(_zzq_default), \
328 (uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1), \
329 (uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3), \
330 (uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5))
331
332static __inline uintptr_t
333valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request,
334 uintptr_t _zzq_arg1, uintptr_t _zzq_arg2,
335 uintptr_t _zzq_arg3, uintptr_t _zzq_arg4,
336 uintptr_t _zzq_arg5)
337{
338 volatile uintptr_t _zzq_args[6];
339 volatile unsigned int _zzq_result;
340 _zzq_args[0] = (uintptr_t)(_zzq_request);
341 _zzq_args[1] = (uintptr_t)(_zzq_arg1);
342 _zzq_args[2] = (uintptr_t)(_zzq_arg2);
343 _zzq_args[3] = (uintptr_t)(_zzq_arg3);
344 _zzq_args[4] = (uintptr_t)(_zzq_arg4);
345 _zzq_args[5] = (uintptr_t)(_zzq_arg5);
346 __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default
347 __SPECIAL_INSTRUCTION_PREAMBLE
348 /* %EDX = client_request ( %EAX ) */
349 __asm xchg ebx,ebx
350 __asm mov _zzq_result, edx
351 }
352 return _zzq_result;
353}
bart7f489812010-08-27 10:05:27 +0000354
355#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
356 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
357 volatile unsigned int __addr; \
358 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
359 /* %EAX = guest_NRADDR */ \
360 __asm xchg ecx,ecx \
361 __asm mov __addr, eax \
362 } \
363 _zzq_orig->nraddr = __addr; \
364 }
365
366#define VALGRIND_CALL_NOREDIR_EAX ERROR
367
florianbb913cd2012-08-28 16:50:39 +0000368#define VALGRIND_VEX_INJECT_IR() \
369 do { \
370 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
371 __asm xchg edi,edi \
372 } \
373 } while (0)
374
bart7f489812010-08-27 10:05:27 +0000375#else
376#error Unsupported compiler.
377#endif
378
379#endif /* PLAT_x86_win32 */
sewardj0ec07f32006-01-12 12:32:32 +0000380
njnf76d27a2009-05-28 01:53:07 +0000381/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000382
sewardjc913c8e2014-05-15 13:50:47 +0000383#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \
384 || (defined(PLAT_amd64_win64) && defined(__GNUC__))
sewardjc8858442006-01-20 15:17:20 +0000385
386typedef
387 struct {
388 unsigned long long int nraddr; /* where's the code? */
389 }
390 OrigFn;
391
sewardj0ec07f32006-01-12 12:32:32 +0000392#define __SPECIAL_INSTRUCTION_PREAMBLE \
393 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000394 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000395
bart575ce8e2011-05-15 07:04:03 +0000396#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
397 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000398 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000399 __extension__ \
400 ({ volatile unsigned long long int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000401 volatile unsigned long long int _zzq_result; \
402 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
403 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
404 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
405 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
406 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000407 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000408 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
409 /* %RDX = client_request ( %RAX ) */ \
410 "xchgq %%rbx,%%rbx" \
411 : "=d" (_zzq_result) \
412 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
413 : "cc", "memory" \
414 ); \
bart575ce8e2011-05-15 07:04:03 +0000415 _zzq_result; \
416 })
sewardj0ec07f32006-01-12 12:32:32 +0000417
sewardjc8858442006-01-20 15:17:20 +0000418#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
419 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
420 volatile unsigned long long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000421 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
422 /* %RAX = guest_NRADDR */ \
423 "xchgq %%rcx,%%rcx" \
424 : "=a" (__addr) \
425 : \
426 : "cc", "memory" \
427 ); \
sewardjc8858442006-01-20 15:17:20 +0000428 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000429 }
430
431#define VALGRIND_CALL_NOREDIR_RAX \
432 __SPECIAL_INSTRUCTION_PREAMBLE \
433 /* call-noredir *%RAX */ \
434 "xchgq %%rdx,%%rdx\n\t"
florianbb913cd2012-08-28 16:50:39 +0000435
436#define VALGRIND_VEX_INJECT_IR() \
437 do { \
438 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
439 "xchgq %%rdi,%%rdi\n\t" \
440 : : : "cc", "memory" \
441 ); \
442 } while (0)
443
njnf76d27a2009-05-28 01:53:07 +0000444#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +0000445
sewardjc913c8e2014-05-15 13:50:47 +0000446/* ------------------------- amd64-Win64 ------------------------- */
447
448#if defined(PLAT_amd64_win64) && !defined(__GNUC__)
449
450#error Unsupported compiler.
451
452#endif /* PLAT_amd64_win64 */
453
sewardjf5c1a7f2006-10-17 01:32:48 +0000454/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000455
sewardjf5c1a7f2006-10-17 01:32:48 +0000456#if defined(PLAT_ppc32_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000457
458typedef
459 struct {
sewardjc8858442006-01-20 15:17:20 +0000460 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000461 }
462 OrigFn;
463
sewardj0ec07f32006-01-12 12:32:32 +0000464#define __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj4decb262014-02-10 12:26:12 +0000465 "rlwinm 0,0,3,0,31 ; rlwinm 0,0,13,0,31\n\t" \
466 "rlwinm 0,0,29,0,31 ; rlwinm 0,0,19,0,31\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000467
bart575ce8e2011-05-15 07:04:03 +0000468#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
469 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000470 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000471 \
bart575ce8e2011-05-15 07:04:03 +0000472 __extension__ \
473 ({ unsigned int _zzq_args[6]; \
sewardj1c5bcb12006-12-08 21:29:46 +0000474 unsigned int _zzq_result; \
475 unsigned int* _zzq_ptr; \
sewardj0ec07f32006-01-12 12:32:32 +0000476 _zzq_args[0] = (unsigned int)(_zzq_request); \
477 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
478 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
479 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
480 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000481 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000482 _zzq_ptr = _zzq_args; \
sewardj1c5bcb12006-12-08 21:29:46 +0000483 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
484 "mr 4,%2\n\t" /*ptr*/ \
485 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj0ec07f32006-01-12 12:32:32 +0000486 /* %R3 = client_request ( %R4 ) */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000487 "or 1,1,1\n\t" \
488 "mr %0,3" /*result*/ \
489 : "=b" (_zzq_result) \
490 : "b" (_zzq_default), "b" (_zzq_ptr) \
491 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000492 _zzq_result; \
493 })
sewardj0ec07f32006-01-12 12:32:32 +0000494
sewardjd68ac3e2006-01-20 14:31:57 +0000495#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
496 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj1c5bcb12006-12-08 21:29:46 +0000497 unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000498 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
499 /* %R3 = guest_NRADDR */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000500 "or 2,2,2\n\t" \
501 "mr %0,3" \
502 : "=b" (__addr) \
sewardj0ec07f32006-01-12 12:32:32 +0000503 : \
sewardj1c5bcb12006-12-08 21:29:46 +0000504 : "cc", "memory", "r3" \
sewardj0ec07f32006-01-12 12:32:32 +0000505 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000506 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000507 }
508
509#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
510 __SPECIAL_INSTRUCTION_PREAMBLE \
511 /* branch-and-link-to-noredir *%R11 */ \
512 "or 3,3,3\n\t"
florian4d261bb2012-08-29 14:59:13 +0000513
514#define VALGRIND_VEX_INJECT_IR() \
515 do { \
516 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
517 "or 5,5,5\n\t" \
518 ); \
519 } while (0)
520
sewardjf5c1a7f2006-10-17 01:32:48 +0000521#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000522
sewardjf5c1a7f2006-10-17 01:32:48 +0000523/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000524
carllcae0cc22014-08-07 23:17:29 +0000525#if defined(PLAT_ppc64be_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000526
527typedef
528 struct {
529 unsigned long long int nraddr; /* where's the code? */
530 unsigned long long int r2; /* what tocptr do we need? */
531 }
532 OrigFn;
533
sewardj1a85f4f2006-01-12 21:15:35 +0000534#define __SPECIAL_INSTRUCTION_PREAMBLE \
535 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
536 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
537
bart575ce8e2011-05-15 07:04:03 +0000538#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
539 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000540 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000541 \
bart575ce8e2011-05-15 07:04:03 +0000542 __extension__ \
543 ({ unsigned long long int _zzq_args[6]; \
sewardj8258a3a2011-10-05 07:39:07 +0000544 unsigned long long int _zzq_result; \
545 unsigned long long int* _zzq_ptr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000546 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
547 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
548 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
549 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
550 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000551 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000552 _zzq_ptr = _zzq_args; \
sewardj8258a3a2011-10-05 07:39:07 +0000553 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
554 "mr 4,%2\n\t" /*ptr*/ \
555 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj1a85f4f2006-01-12 21:15:35 +0000556 /* %R3 = client_request ( %R4 ) */ \
sewardj8258a3a2011-10-05 07:39:07 +0000557 "or 1,1,1\n\t" \
558 "mr %0,3" /*result*/ \
559 : "=b" (_zzq_result) \
560 : "b" (_zzq_default), "b" (_zzq_ptr) \
561 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000562 _zzq_result; \
563 })
sewardj1a85f4f2006-01-12 21:15:35 +0000564
sewardjd68ac3e2006-01-20 14:31:57 +0000565#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
566 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj8258a3a2011-10-05 07:39:07 +0000567 unsigned long long int __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000568 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
569 /* %R3 = guest_NRADDR */ \
sewardj8258a3a2011-10-05 07:39:07 +0000570 "or 2,2,2\n\t" \
571 "mr %0,3" \
572 : "=b" (__addr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000573 : \
sewardj8258a3a2011-10-05 07:39:07 +0000574 : "cc", "memory", "r3" \
sewardj1a85f4f2006-01-12 21:15:35 +0000575 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000576 _zzq_orig->nraddr = __addr; \
577 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
578 /* %R3 = guest_NRADDR_GPR2 */ \
sewardj8258a3a2011-10-05 07:39:07 +0000579 "or 4,4,4\n\t" \
580 "mr %0,3" \
581 : "=b" (__addr) \
sewardjd68ac3e2006-01-20 14:31:57 +0000582 : \
sewardj8258a3a2011-10-05 07:39:07 +0000583 : "cc", "memory", "r3" \
sewardjd68ac3e2006-01-20 14:31:57 +0000584 ); \
585 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000586 }
587
588#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
589 __SPECIAL_INSTRUCTION_PREAMBLE \
590 /* branch-and-link-to-noredir *%R11 */ \
591 "or 3,3,3\n\t"
592
florianbb913cd2012-08-28 16:50:39 +0000593#define VALGRIND_VEX_INJECT_IR() \
594 do { \
595 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
596 "or 5,5,5\n\t" \
597 ); \
598 } while (0)
599
carllcae0cc22014-08-07 23:17:29 +0000600#endif /* PLAT_ppc64be_linux */
601
cerion85665ca2005-06-20 15:51:07 +0000602
sewardj59570ff2010-01-01 11:59:33 +0000603/* ------------------------- arm-linux ------------------------- */
604
605#if defined(PLAT_arm_linux)
606
607typedef
608 struct {
609 unsigned int nraddr; /* where's the code? */
610 }
611 OrigFn;
612
613#define __SPECIAL_INSTRUCTION_PREAMBLE \
614 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
615 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
616
bart575ce8e2011-05-15 07:04:03 +0000617#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
618 _zzq_default, _zzq_request, \
sewardj59570ff2010-01-01 11:59:33 +0000619 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
620 \
bart575ce8e2011-05-15 07:04:03 +0000621 __extension__ \
622 ({volatile unsigned int _zzq_args[6]; \
sewardj59570ff2010-01-01 11:59:33 +0000623 volatile unsigned int _zzq_result; \
624 _zzq_args[0] = (unsigned int)(_zzq_request); \
625 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
626 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
627 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
628 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
629 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
630 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
631 "mov r4, %2\n\t" /*ptr*/ \
632 __SPECIAL_INSTRUCTION_PREAMBLE \
633 /* R3 = client_request ( R4 ) */ \
634 "orr r10, r10, r10\n\t" \
635 "mov %0, r3" /*result*/ \
636 : "=r" (_zzq_result) \
637 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
638 : "cc","memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000639 _zzq_result; \
640 })
sewardj59570ff2010-01-01 11:59:33 +0000641
642#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
643 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
644 unsigned int __addr; \
645 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
646 /* R3 = guest_NRADDR */ \
647 "orr r11, r11, r11\n\t" \
648 "mov %0, r3" \
649 : "=r" (__addr) \
650 : \
651 : "cc", "memory", "r3" \
652 ); \
653 _zzq_orig->nraddr = __addr; \
654 }
655
656#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
657 __SPECIAL_INSTRUCTION_PREAMBLE \
658 /* branch-and-link-to-noredir *%R4 */ \
659 "orr r12, r12, r12\n\t"
660
florianbb913cd2012-08-28 16:50:39 +0000661#define VALGRIND_VEX_INJECT_IR() \
662 do { \
663 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
sewardjc379fec2012-09-03 21:51:02 +0000664 "orr r9, r9, r9\n\t" \
florianbb913cd2012-08-28 16:50:39 +0000665 : : : "cc", "memory" \
666 ); \
667 } while (0)
668
sewardj59570ff2010-01-01 11:59:33 +0000669#endif /* PLAT_arm_linux */
670
sewardjf0c12502014-01-12 12:54:00 +0000671/* ------------------------ arm64-linux ------------------------- */
672
673#if defined(PLAT_arm64_linux)
674
675typedef
676 struct {
677 unsigned long long int nraddr; /* where's the code? */
678 }
679 OrigFn;
680
681#define __SPECIAL_INSTRUCTION_PREAMBLE \
682 "ror x12, x12, #3 ; ror x12, x12, #13 \n\t" \
683 "ror x12, x12, #51 ; ror x12, x12, #61 \n\t"
684
685#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
686 _zzq_default, _zzq_request, \
687 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
688 \
689 __extension__ \
690 ({volatile unsigned long long int _zzq_args[6]; \
691 volatile unsigned long long int _zzq_result; \
692 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
693 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
694 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
695 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
696 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
697 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
698 __asm__ volatile("mov x3, %1\n\t" /*default*/ \
699 "mov x4, %2\n\t" /*ptr*/ \
700 __SPECIAL_INSTRUCTION_PREAMBLE \
701 /* X3 = client_request ( X4 ) */ \
702 "orr x10, x10, x10\n\t" \
703 "mov %0, x3" /*result*/ \
704 : "=r" (_zzq_result) \
705 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
706 : "cc","memory", "x3", "x4"); \
707 _zzq_result; \
708 })
709
710#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
711 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
712 unsigned long long int __addr; \
713 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
714 /* X3 = guest_NRADDR */ \
715 "orr x11, x11, x11\n\t" \
716 "mov %0, x3" \
717 : "=r" (__addr) \
718 : \
719 : "cc", "memory", "x3" \
720 ); \
721 _zzq_orig->nraddr = __addr; \
722 }
723
724#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
725 __SPECIAL_INSTRUCTION_PREAMBLE \
726 /* branch-and-link-to-noredir X8 */ \
727 "orr x12, x12, x12\n\t"
728
729#define VALGRIND_VEX_INJECT_IR() \
730 do { \
731 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
732 "orr x9, x9, x9\n\t" \
733 : : : "cc", "memory" \
734 ); \
735 } while (0)
736
737#endif /* PLAT_arm64_linux */
738
sewardjb5b87402011-03-07 16:05:35 +0000739/* ------------------------ s390x-linux ------------------------ */
740
741#if defined(PLAT_s390x_linux)
742
743typedef
744 struct {
745 unsigned long long int nraddr; /* where's the code? */
746 }
747 OrigFn;
748
749/* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific
750 * code. This detection is implemented in platform specific toIR.c
751 * (e.g. VEX/priv/guest_s390_decoder.c).
752 */
753#define __SPECIAL_INSTRUCTION_PREAMBLE \
754 "lr 15,15\n\t" \
755 "lr 1,1\n\t" \
756 "lr 2,2\n\t" \
757 "lr 3,3\n\t"
758
759#define __CLIENT_REQUEST_CODE "lr 2,2\n\t"
760#define __GET_NR_CONTEXT_CODE "lr 3,3\n\t"
761#define __CALL_NO_REDIR_CODE "lr 4,4\n\t"
florianbb913cd2012-08-28 16:50:39 +0000762#define __VEX_INJECT_IR_CODE "lr 5,5\n\t"
sewardjb5b87402011-03-07 16:05:35 +0000763
bart575ce8e2011-05-15 07:04:03 +0000764#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
765 _zzq_default, _zzq_request, \
sewardjb5b87402011-03-07 16:05:35 +0000766 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000767 __extension__ \
768 ({volatile unsigned long long int _zzq_args[6]; \
sewardjb5b87402011-03-07 16:05:35 +0000769 volatile unsigned long long int _zzq_result; \
770 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
771 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
772 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
773 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
774 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
775 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
776 __asm__ volatile(/* r2 = args */ \
777 "lgr 2,%1\n\t" \
778 /* r3 = default */ \
779 "lgr 3,%2\n\t" \
780 __SPECIAL_INSTRUCTION_PREAMBLE \
781 __CLIENT_REQUEST_CODE \
782 /* results = r3 */ \
783 "lgr %0, 3\n\t" \
784 : "=d" (_zzq_result) \
785 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
786 : "cc", "2", "3", "memory" \
787 ); \
bart575ce8e2011-05-15 07:04:03 +0000788 _zzq_result; \
789 })
sewardjb5b87402011-03-07 16:05:35 +0000790
791#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
792 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
793 volatile unsigned long long int __addr; \
794 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
795 __GET_NR_CONTEXT_CODE \
796 "lgr %0, 3\n\t" \
797 : "=a" (__addr) \
798 : \
799 : "cc", "3", "memory" \
800 ); \
801 _zzq_orig->nraddr = __addr; \
802 }
803
804#define VALGRIND_CALL_NOREDIR_R1 \
805 __SPECIAL_INSTRUCTION_PREAMBLE \
806 __CALL_NO_REDIR_CODE
807
florianbb913cd2012-08-28 16:50:39 +0000808#define VALGRIND_VEX_INJECT_IR() \
809 do { \
810 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
811 __VEX_INJECT_IR_CODE); \
812 } while (0)
813
sewardjb5b87402011-03-07 16:05:35 +0000814#endif /* PLAT_s390x_linux */
815
sewardj5db15402012-06-07 09:13:21 +0000816/* ------------------------- mips32-linux ---------------- */
817
818#if defined(PLAT_mips32_linux)
819
820typedef
821 struct {
822 unsigned int nraddr; /* where's the code? */
823 }
824 OrigFn;
825
826/* .word 0x342
827 * .word 0x742
828 * .word 0xC2
829 * .word 0x4C2*/
830#define __SPECIAL_INSTRUCTION_PREAMBLE \
831 "srl $0, $0, 13\n\t" \
832 "srl $0, $0, 29\n\t" \
833 "srl $0, $0, 3\n\t" \
834 "srl $0, $0, 19\n\t"
835
836#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
837 _zzq_default, _zzq_request, \
838 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
839 __extension__ \
840 ({ volatile unsigned int _zzq_args[6]; \
841 volatile unsigned int _zzq_result; \
842 _zzq_args[0] = (unsigned int)(_zzq_request); \
843 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
844 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
845 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
846 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
847 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
848 __asm__ volatile("move $11, %1\n\t" /*default*/ \
849 "move $12, %2\n\t" /*ptr*/ \
850 __SPECIAL_INSTRUCTION_PREAMBLE \
851 /* T3 = client_request ( T4 ) */ \
852 "or $13, $13, $13\n\t" \
853 "move %0, $11\n\t" /*result*/ \
854 : "=r" (_zzq_result) \
855 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
petarj4df0bfc2013-02-27 23:17:33 +0000856 : "$11", "$12"); \
sewardj5db15402012-06-07 09:13:21 +0000857 _zzq_result; \
858 })
859
860#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
861 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
862 volatile unsigned int __addr; \
863 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
864 /* %t9 = guest_NRADDR */ \
865 "or $14, $14, $14\n\t" \
866 "move %0, $11" /*result*/ \
867 : "=r" (__addr) \
868 : \
petarj4df0bfc2013-02-27 23:17:33 +0000869 : "$11" \
sewardj5db15402012-06-07 09:13:21 +0000870 ); \
871 _zzq_orig->nraddr = __addr; \
872 }
873
874#define VALGRIND_CALL_NOREDIR_T9 \
875 __SPECIAL_INSTRUCTION_PREAMBLE \
876 /* call-noredir *%t9 */ \
florianbb913cd2012-08-28 16:50:39 +0000877 "or $15, $15, $15\n\t"
878
879#define VALGRIND_VEX_INJECT_IR() \
880 do { \
881 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
882 "or $11, $11, $11\n\t" \
883 ); \
884 } while (0)
885
886
sewardj5db15402012-06-07 09:13:21 +0000887#endif /* PLAT_mips32_linux */
888
petarj4df0bfc2013-02-27 23:17:33 +0000889/* ------------------------- mips64-linux ---------------- */
890
891#if defined(PLAT_mips64_linux)
892
893typedef
894 struct {
895 unsigned long long nraddr; /* where's the code? */
896 }
897 OrigFn;
898
899/* dsll $0,$0, 3
900 * dsll $0,$0, 13
901 * dsll $0,$0, 29
902 * dsll $0,$0, 19*/
903#define __SPECIAL_INSTRUCTION_PREAMBLE \
904 "dsll $0,$0, 3 ; dsll $0,$0,13\n\t" \
905 "dsll $0,$0,29 ; dsll $0,$0,19\n\t"
906
907#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
908 _zzq_default, _zzq_request, \
909 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
910 __extension__ \
911 ({ volatile unsigned long long int _zzq_args[6]; \
912 volatile unsigned long long int _zzq_result; \
913 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
914 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
915 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
916 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
917 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
918 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
919 __asm__ volatile("move $11, %1\n\t" /*default*/ \
920 "move $12, %2\n\t" /*ptr*/ \
921 __SPECIAL_INSTRUCTION_PREAMBLE \
922 /* $11 = client_request ( $12 ) */ \
923 "or $13, $13, $13\n\t" \
924 "move %0, $11\n\t" /*result*/ \
925 : "=r" (_zzq_result) \
926 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
927 : "$11", "$12"); \
928 _zzq_result; \
929 })
930
931#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
932 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
933 volatile unsigned long long int __addr; \
934 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
935 /* $11 = guest_NRADDR */ \
936 "or $14, $14, $14\n\t" \
937 "move %0, $11" /*result*/ \
938 : "=r" (__addr) \
939 : \
940 : "$11"); \
941 _zzq_orig->nraddr = __addr; \
942 }
943
944#define VALGRIND_CALL_NOREDIR_T9 \
945 __SPECIAL_INSTRUCTION_PREAMBLE \
946 /* call-noredir $25 */ \
947 "or $15, $15, $15\n\t"
948
949#define VALGRIND_VEX_INJECT_IR() \
950 do { \
951 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
952 "or $11, $11, $11\n\t" \
953 ); \
954 } while (0)
955
956#endif /* PLAT_mips64_linux */
957
sewardjf5c1a7f2006-10-17 01:32:48 +0000958/* Insert assembly code for other platforms here... */
njn26aba4d2005-05-16 13:31:23 +0000959
sewardj37091fb2002-11-16 11:06:50 +0000960#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +0000961
nethercote69d9c462004-10-26 13:00:12 +0000962
njn30d76c62005-06-18 15:07:39 +0000963/* ------------------------------------------------------------------ */
sewardjf5c1a7f2006-10-17 01:32:48 +0000964/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
sewardj0ec07f32006-01-12 12:32:32 +0000965/* ugly. It's the least-worst tradeoff I can think of. */
966/* ------------------------------------------------------------------ */
967
968/* This section defines magic (a.k.a appalling-hack) macros for doing
969 guaranteed-no-redirection macros, so as to get from function
970 wrappers to the functions they are wrapping. The whole point is to
971 construct standard call sequences, but to do the call itself with a
972 special no-redirect call pseudo-instruction that the JIT
973 understands and handles specially. This section is long and
974 repetitious, and I can't see a way to make it shorter.
975
976 The naming scheme is as follows:
977
978 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
979
980 'W' stands for "word" and 'v' for "void". Hence there are
981 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
982 and for each, the possibility of returning a word-typed result, or
983 no result.
984*/
985
986/* Use these to write the name of your wrapper. NOTE: duplicates
sewardj85cf9002011-08-16 09:54:00 +0000987 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. NOTE also: inserts
988 the default behaviour equivalance class tag "0000" into the name.
989 See pub_tool_redir.h for details -- normally you don't need to
990 think about this, though. */
sewardj0ec07f32006-01-12 12:32:32 +0000991
njn5f5ef2a2009-05-11 08:01:09 +0000992/* Use an extra level of macroisation so as to ensure the soname/fnname
993 args are fully macro-expanded before pasting them together. */
994#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
995
sewardj0ec07f32006-01-12 12:32:32 +0000996#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +0000997 VG_CONCAT4(_vgw00000ZU_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000998
999#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +00001000 VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +00001001
sewardjd68ac3e2006-01-20 14:31:57 +00001002/* Use this macro from within a wrapper function to collect the
1003 context (address and possibly other info) of the original function.
1004 Once you have that you can then use it in one of the CALL_FN_
1005 macros. The type of the argument _lval is OrigFn. */
1006#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +00001007
sewardj573f8bc2012-06-05 07:12:15 +00001008/* Also provide end-user facilities for function replacement, rather
1009 than wrapping. A replacement function differs from a wrapper in
1010 that it has no way to get hold of the original function being
1011 called, and hence no way to call onwards to it. In a replacement
1012 function, VALGRIND_GET_ORIG_FN always returns zero. */
1013
1014#define I_REPLACE_SONAME_FNNAME_ZU(soname,fnname) \
1015 VG_CONCAT4(_vgr00000ZU_,soname,_,fnname)
1016
1017#define I_REPLACE_SONAME_FNNAME_ZZ(soname,fnname) \
1018 VG_CONCAT4(_vgr00000ZZ_,soname,_,fnname)
1019
sewardj0ec07f32006-01-12 12:32:32 +00001020/* Derivatives of the main macros below, for calling functions
1021 returning void. */
1022
1023#define CALL_FN_v_v(fnptr) \
1024 do { volatile unsigned long _junk; \
1025 CALL_FN_W_v(_junk,fnptr); } while (0)
1026
1027#define CALL_FN_v_W(fnptr, arg1) \
1028 do { volatile unsigned long _junk; \
1029 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
1030
1031#define CALL_FN_v_WW(fnptr, arg1,arg2) \
1032 do { volatile unsigned long _junk; \
1033 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
1034
sewardj5ce4b152006-03-11 12:57:41 +00001035#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
1036 do { volatile unsigned long _junk; \
1037 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
1038
njn2b5f0a92009-05-19 01:24:50 +00001039#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
1040 do { volatile unsigned long _junk; \
1041 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
1042
1043#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
1044 do { volatile unsigned long _junk; \
1045 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
1046
1047#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
1048 do { volatile unsigned long _junk; \
1049 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
1050
1051#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
1052 do { volatile unsigned long _junk; \
1053 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
1054
njnf76d27a2009-05-28 01:53:07 +00001055/* ------------------------- x86-{linux,darwin} ---------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001056
njnf76d27a2009-05-28 01:53:07 +00001057#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
sewardj0ec07f32006-01-12 12:32:32 +00001058
1059/* These regs are trashed by the hidden call. No need to mention eax
1060 as gcc can already see that, plus causes gcc to bomb. */
1061#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
1062
tom4118e0f2012-08-02 09:23:45 +00001063/* Macros to save and align the stack before making a function
1064 call and restore it afterwards as gcc may not keep the stack
1065 pointer aligned if it doesn't realise calls are being made
1066 to other functions. */
1067
1068#define VALGRIND_ALIGN_STACK \
1069 "movl %%esp,%%edi\n\t" \
1070 "andl $0xfffffff0,%%esp\n\t"
1071#define VALGRIND_RESTORE_STACK \
1072 "movl %%edi,%%esp\n\t"
1073
sewardj0ec07f32006-01-12 12:32:32 +00001074/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
1075 long) == 4. */
1076
sewardj66226cc2006-01-20 15:46:46 +00001077#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001078 do { \
sewardj66226cc2006-01-20 15:46:46 +00001079 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001080 volatile unsigned long _argvec[1]; \
1081 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001082 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001083 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001084 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001085 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1086 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001087 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001088 : /*out*/ "=a" (_res) \
1089 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001090 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001091 ); \
1092 lval = (__typeof__(lval)) _res; \
1093 } while (0)
1094
sewardj66226cc2006-01-20 15:46:46 +00001095#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001096 do { \
sewardj66226cc2006-01-20 15:46:46 +00001097 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001098 volatile unsigned long _argvec[2]; \
1099 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001100 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001101 _argvec[1] = (unsigned long)(arg1); \
1102 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001103 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001104 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001105 "pushl 4(%%eax)\n\t" \
1106 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1107 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001108 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001109 : /*out*/ "=a" (_res) \
1110 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001111 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001112 ); \
1113 lval = (__typeof__(lval)) _res; \
1114 } while (0)
1115
sewardj66226cc2006-01-20 15:46:46 +00001116#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001117 do { \
sewardj66226cc2006-01-20 15:46:46 +00001118 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001119 volatile unsigned long _argvec[3]; \
1120 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001121 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001122 _argvec[1] = (unsigned long)(arg1); \
1123 _argvec[2] = (unsigned long)(arg2); \
1124 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001125 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001126 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001127 "pushl 8(%%eax)\n\t" \
1128 "pushl 4(%%eax)\n\t" \
1129 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1130 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001131 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001132 : /*out*/ "=a" (_res) \
1133 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001134 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001135 ); \
1136 lval = (__typeof__(lval)) _res; \
1137 } while (0)
1138
sewardj9e8b07a2006-02-18 21:13:29 +00001139#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1140 do { \
1141 volatile OrigFn _orig = (orig); \
1142 volatile unsigned long _argvec[4]; \
1143 volatile unsigned long _res; \
1144 _argvec[0] = (unsigned long)_orig.nraddr; \
1145 _argvec[1] = (unsigned long)(arg1); \
1146 _argvec[2] = (unsigned long)(arg2); \
1147 _argvec[3] = (unsigned long)(arg3); \
1148 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001149 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001150 "subl $4, %%esp\n\t" \
sewardj9e8b07a2006-02-18 21:13:29 +00001151 "pushl 12(%%eax)\n\t" \
1152 "pushl 8(%%eax)\n\t" \
1153 "pushl 4(%%eax)\n\t" \
1154 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1155 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001156 VALGRIND_RESTORE_STACK \
sewardj9e8b07a2006-02-18 21:13:29 +00001157 : /*out*/ "=a" (_res) \
1158 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001159 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj9e8b07a2006-02-18 21:13:29 +00001160 ); \
1161 lval = (__typeof__(lval)) _res; \
1162 } while (0)
1163
sewardj66226cc2006-01-20 15:46:46 +00001164#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
sewardj0ec07f32006-01-12 12:32:32 +00001165 do { \
sewardj66226cc2006-01-20 15:46:46 +00001166 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001167 volatile unsigned long _argvec[5]; \
1168 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001169 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001170 _argvec[1] = (unsigned long)(arg1); \
1171 _argvec[2] = (unsigned long)(arg2); \
1172 _argvec[3] = (unsigned long)(arg3); \
1173 _argvec[4] = (unsigned long)(arg4); \
1174 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001175 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001176 "pushl 16(%%eax)\n\t" \
1177 "pushl 12(%%eax)\n\t" \
1178 "pushl 8(%%eax)\n\t" \
1179 "pushl 4(%%eax)\n\t" \
1180 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1181 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001182 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001183 : /*out*/ "=a" (_res) \
1184 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001185 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001186 ); \
1187 lval = (__typeof__(lval)) _res; \
1188 } while (0)
1189
sewardj66226cc2006-01-20 15:46:46 +00001190#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +00001191 do { \
sewardj66226cc2006-01-20 15:46:46 +00001192 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001193 volatile unsigned long _argvec[6]; \
1194 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001195 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001196 _argvec[1] = (unsigned long)(arg1); \
1197 _argvec[2] = (unsigned long)(arg2); \
1198 _argvec[3] = (unsigned long)(arg3); \
1199 _argvec[4] = (unsigned long)(arg4); \
1200 _argvec[5] = (unsigned long)(arg5); \
1201 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001202 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001203 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001204 "pushl 20(%%eax)\n\t" \
1205 "pushl 16(%%eax)\n\t" \
1206 "pushl 12(%%eax)\n\t" \
1207 "pushl 8(%%eax)\n\t" \
1208 "pushl 4(%%eax)\n\t" \
1209 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1210 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001211 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001212 : /*out*/ "=a" (_res) \
1213 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001214 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001215 ); \
1216 lval = (__typeof__(lval)) _res; \
1217 } while (0)
1218
sewardj66226cc2006-01-20 15:46:46 +00001219#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +00001220 do { \
sewardj66226cc2006-01-20 15:46:46 +00001221 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001222 volatile unsigned long _argvec[7]; \
1223 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001224 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001225 _argvec[1] = (unsigned long)(arg1); \
1226 _argvec[2] = (unsigned long)(arg2); \
1227 _argvec[3] = (unsigned long)(arg3); \
1228 _argvec[4] = (unsigned long)(arg4); \
1229 _argvec[5] = (unsigned long)(arg5); \
1230 _argvec[6] = (unsigned long)(arg6); \
1231 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001232 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001233 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001234 "pushl 24(%%eax)\n\t" \
1235 "pushl 20(%%eax)\n\t" \
1236 "pushl 16(%%eax)\n\t" \
1237 "pushl 12(%%eax)\n\t" \
1238 "pushl 8(%%eax)\n\t" \
1239 "pushl 4(%%eax)\n\t" \
1240 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1241 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001242 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001243 : /*out*/ "=a" (_res) \
1244 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001245 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001246 ); \
1247 lval = (__typeof__(lval)) _res; \
1248 } while (0)
1249
sewardj66226cc2006-01-20 15:46:46 +00001250#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1251 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +00001252 do { \
sewardj66226cc2006-01-20 15:46:46 +00001253 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001254 volatile unsigned long _argvec[8]; \
1255 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001256 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001257 _argvec[1] = (unsigned long)(arg1); \
1258 _argvec[2] = (unsigned long)(arg2); \
1259 _argvec[3] = (unsigned long)(arg3); \
1260 _argvec[4] = (unsigned long)(arg4); \
1261 _argvec[5] = (unsigned long)(arg5); \
1262 _argvec[6] = (unsigned long)(arg6); \
1263 _argvec[7] = (unsigned long)(arg7); \
1264 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001265 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001266 "subl $4, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001267 "pushl 28(%%eax)\n\t" \
1268 "pushl 24(%%eax)\n\t" \
1269 "pushl 20(%%eax)\n\t" \
1270 "pushl 16(%%eax)\n\t" \
1271 "pushl 12(%%eax)\n\t" \
1272 "pushl 8(%%eax)\n\t" \
1273 "pushl 4(%%eax)\n\t" \
1274 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1275 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001276 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001277 : /*out*/ "=a" (_res) \
1278 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001279 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001280 ); \
1281 lval = (__typeof__(lval)) _res; \
1282 } while (0)
1283
sewardj66226cc2006-01-20 15:46:46 +00001284#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1285 arg7,arg8) \
sewardj0ec07f32006-01-12 12:32:32 +00001286 do { \
sewardj66226cc2006-01-20 15:46:46 +00001287 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001288 volatile unsigned long _argvec[9]; \
1289 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001290 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001291 _argvec[1] = (unsigned long)(arg1); \
1292 _argvec[2] = (unsigned long)(arg2); \
1293 _argvec[3] = (unsigned long)(arg3); \
1294 _argvec[4] = (unsigned long)(arg4); \
1295 _argvec[5] = (unsigned long)(arg5); \
1296 _argvec[6] = (unsigned long)(arg6); \
1297 _argvec[7] = (unsigned long)(arg7); \
1298 _argvec[8] = (unsigned long)(arg8); \
1299 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001300 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001301 "pushl 32(%%eax)\n\t" \
1302 "pushl 28(%%eax)\n\t" \
1303 "pushl 24(%%eax)\n\t" \
1304 "pushl 20(%%eax)\n\t" \
1305 "pushl 16(%%eax)\n\t" \
1306 "pushl 12(%%eax)\n\t" \
1307 "pushl 8(%%eax)\n\t" \
1308 "pushl 4(%%eax)\n\t" \
1309 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1310 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001311 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001312 : /*out*/ "=a" (_res) \
1313 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001314 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001315 ); \
1316 lval = (__typeof__(lval)) _res; \
1317 } while (0)
1318
sewardj45fa5b02006-03-09 19:06:23 +00001319#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1320 arg7,arg8,arg9) \
1321 do { \
1322 volatile OrigFn _orig = (orig); \
1323 volatile unsigned long _argvec[10]; \
1324 volatile unsigned long _res; \
1325 _argvec[0] = (unsigned long)_orig.nraddr; \
1326 _argvec[1] = (unsigned long)(arg1); \
1327 _argvec[2] = (unsigned long)(arg2); \
1328 _argvec[3] = (unsigned long)(arg3); \
1329 _argvec[4] = (unsigned long)(arg4); \
1330 _argvec[5] = (unsigned long)(arg5); \
1331 _argvec[6] = (unsigned long)(arg6); \
1332 _argvec[7] = (unsigned long)(arg7); \
1333 _argvec[8] = (unsigned long)(arg8); \
1334 _argvec[9] = (unsigned long)(arg9); \
1335 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001336 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001337 "subl $12, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001338 "pushl 36(%%eax)\n\t" \
1339 "pushl 32(%%eax)\n\t" \
1340 "pushl 28(%%eax)\n\t" \
1341 "pushl 24(%%eax)\n\t" \
1342 "pushl 20(%%eax)\n\t" \
1343 "pushl 16(%%eax)\n\t" \
1344 "pushl 12(%%eax)\n\t" \
1345 "pushl 8(%%eax)\n\t" \
1346 "pushl 4(%%eax)\n\t" \
1347 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1348 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001349 VALGRIND_RESTORE_STACK \
sewardj45fa5b02006-03-09 19:06:23 +00001350 : /*out*/ "=a" (_res) \
1351 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001352 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj45fa5b02006-03-09 19:06:23 +00001353 ); \
1354 lval = (__typeof__(lval)) _res; \
1355 } while (0)
1356
1357#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1358 arg7,arg8,arg9,arg10) \
1359 do { \
1360 volatile OrigFn _orig = (orig); \
1361 volatile unsigned long _argvec[11]; \
1362 volatile unsigned long _res; \
1363 _argvec[0] = (unsigned long)_orig.nraddr; \
1364 _argvec[1] = (unsigned long)(arg1); \
1365 _argvec[2] = (unsigned long)(arg2); \
1366 _argvec[3] = (unsigned long)(arg3); \
1367 _argvec[4] = (unsigned long)(arg4); \
1368 _argvec[5] = (unsigned long)(arg5); \
1369 _argvec[6] = (unsigned long)(arg6); \
1370 _argvec[7] = (unsigned long)(arg7); \
1371 _argvec[8] = (unsigned long)(arg8); \
1372 _argvec[9] = (unsigned long)(arg9); \
1373 _argvec[10] = (unsigned long)(arg10); \
1374 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001375 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001376 "subl $8, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001377 "pushl 40(%%eax)\n\t" \
1378 "pushl 36(%%eax)\n\t" \
1379 "pushl 32(%%eax)\n\t" \
1380 "pushl 28(%%eax)\n\t" \
1381 "pushl 24(%%eax)\n\t" \
1382 "pushl 20(%%eax)\n\t" \
1383 "pushl 16(%%eax)\n\t" \
1384 "pushl 12(%%eax)\n\t" \
1385 "pushl 8(%%eax)\n\t" \
1386 "pushl 4(%%eax)\n\t" \
1387 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1388 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001389 VALGRIND_RESTORE_STACK \
sewardj45fa5b02006-03-09 19:06:23 +00001390 : /*out*/ "=a" (_res) \
1391 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001392 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj45fa5b02006-03-09 19:06:23 +00001393 ); \
1394 lval = (__typeof__(lval)) _res; \
1395 } while (0)
1396
sewardj5ce4b152006-03-11 12:57:41 +00001397#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1398 arg6,arg7,arg8,arg9,arg10, \
1399 arg11) \
1400 do { \
1401 volatile OrigFn _orig = (orig); \
1402 volatile unsigned long _argvec[12]; \
1403 volatile unsigned long _res; \
1404 _argvec[0] = (unsigned long)_orig.nraddr; \
1405 _argvec[1] = (unsigned long)(arg1); \
1406 _argvec[2] = (unsigned long)(arg2); \
1407 _argvec[3] = (unsigned long)(arg3); \
1408 _argvec[4] = (unsigned long)(arg4); \
1409 _argvec[5] = (unsigned long)(arg5); \
1410 _argvec[6] = (unsigned long)(arg6); \
1411 _argvec[7] = (unsigned long)(arg7); \
1412 _argvec[8] = (unsigned long)(arg8); \
1413 _argvec[9] = (unsigned long)(arg9); \
1414 _argvec[10] = (unsigned long)(arg10); \
1415 _argvec[11] = (unsigned long)(arg11); \
1416 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001417 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001418 "subl $4, %%esp\n\t" \
sewardj5ce4b152006-03-11 12:57:41 +00001419 "pushl 44(%%eax)\n\t" \
1420 "pushl 40(%%eax)\n\t" \
1421 "pushl 36(%%eax)\n\t" \
1422 "pushl 32(%%eax)\n\t" \
1423 "pushl 28(%%eax)\n\t" \
1424 "pushl 24(%%eax)\n\t" \
1425 "pushl 20(%%eax)\n\t" \
1426 "pushl 16(%%eax)\n\t" \
1427 "pushl 12(%%eax)\n\t" \
1428 "pushl 8(%%eax)\n\t" \
1429 "pushl 4(%%eax)\n\t" \
1430 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1431 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001432 VALGRIND_RESTORE_STACK \
sewardj5ce4b152006-03-11 12:57:41 +00001433 : /*out*/ "=a" (_res) \
1434 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001435 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj5ce4b152006-03-11 12:57:41 +00001436 ); \
1437 lval = (__typeof__(lval)) _res; \
1438 } while (0)
1439
sewardj66226cc2006-01-20 15:46:46 +00001440#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1441 arg6,arg7,arg8,arg9,arg10, \
1442 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +00001443 do { \
sewardj66226cc2006-01-20 15:46:46 +00001444 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001445 volatile unsigned long _argvec[13]; \
1446 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001447 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001448 _argvec[1] = (unsigned long)(arg1); \
1449 _argvec[2] = (unsigned long)(arg2); \
1450 _argvec[3] = (unsigned long)(arg3); \
1451 _argvec[4] = (unsigned long)(arg4); \
1452 _argvec[5] = (unsigned long)(arg5); \
1453 _argvec[6] = (unsigned long)(arg6); \
1454 _argvec[7] = (unsigned long)(arg7); \
1455 _argvec[8] = (unsigned long)(arg8); \
1456 _argvec[9] = (unsigned long)(arg9); \
1457 _argvec[10] = (unsigned long)(arg10); \
1458 _argvec[11] = (unsigned long)(arg11); \
1459 _argvec[12] = (unsigned long)(arg12); \
1460 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001461 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001462 "pushl 48(%%eax)\n\t" \
1463 "pushl 44(%%eax)\n\t" \
1464 "pushl 40(%%eax)\n\t" \
1465 "pushl 36(%%eax)\n\t" \
1466 "pushl 32(%%eax)\n\t" \
1467 "pushl 28(%%eax)\n\t" \
1468 "pushl 24(%%eax)\n\t" \
1469 "pushl 20(%%eax)\n\t" \
1470 "pushl 16(%%eax)\n\t" \
1471 "pushl 12(%%eax)\n\t" \
1472 "pushl 8(%%eax)\n\t" \
1473 "pushl 4(%%eax)\n\t" \
1474 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1475 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001476 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001477 : /*out*/ "=a" (_res) \
1478 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001479 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001480 ); \
1481 lval = (__typeof__(lval)) _res; \
1482 } while (0)
1483
njnf76d27a2009-05-28 01:53:07 +00001484#endif /* PLAT_x86_linux || PLAT_x86_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001485
njnf76d27a2009-05-28 01:53:07 +00001486/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001487
njnf76d27a2009-05-28 01:53:07 +00001488#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardj0ec07f32006-01-12 12:32:32 +00001489
1490/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1491
1492/* These regs are trashed by the hidden call. */
1493#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1494 "rdi", "r8", "r9", "r10", "r11"
1495
sewardjdfa55cf2010-10-06 22:07:06 +00001496/* This is all pretty complex. It's so as to make stack unwinding
1497 work reliably. See bug 243270. The basic problem is the sub and
1498 add of 128 of %rsp in all of the following macros. If gcc believes
1499 the CFA is in %rsp, then unwinding may fail, because what's at the
1500 CFA is not what gcc "expected" when it constructs the CFIs for the
1501 places where the macros are instantiated.
1502
1503 But we can't just add a CFI annotation to increase the CFA offset
1504 by 128, to match the sub of 128 from %rsp, because we don't know
1505 whether gcc has chosen %rsp as the CFA at that point, or whether it
1506 has chosen some other register (eg, %rbp). In the latter case,
1507 adding a CFI annotation to change the CFA offset is simply wrong.
1508
1509 So the solution is to get hold of the CFA using
sewardj8d1dc152010-10-08 17:43:26 +00001510 __builtin_dwarf_cfa(), put it in a known register, and add a
sewardjdfa55cf2010-10-06 22:07:06 +00001511 CFI annotation to say what the register is. We choose %rbp for
1512 this (perhaps perversely), because:
1513
1514 (1) %rbp is already subject to unwinding. If a new register was
1515 chosen then the unwinder would have to unwind it in all stack
1516 traces, which is expensive, and
1517
1518 (2) %rbp is already subject to precise exception updates in the
1519 JIT. If a new register was chosen, we'd have to have precise
1520 exceptions for it too, which reduces performance of the
1521 generated code.
1522
1523 However .. one extra complication. We can't just whack the result
sewardj8d1dc152010-10-08 17:43:26 +00001524 of __builtin_dwarf_cfa() into %rbp and then add %rbp to the
sewardjdfa55cf2010-10-06 22:07:06 +00001525 list of trashed registers at the end of the inline assembly
1526 fragments; gcc won't allow %rbp to appear in that list. Hence
1527 instead we need to stash %rbp in %r15 for the duration of the asm,
1528 and say that %r15 is trashed instead. gcc seems happy to go with
1529 that.
1530
1531 Oh .. and this all needs to be conditionalised so that it is
1532 unchanged from before this commit, when compiled with older gccs
sewardj8d1dc152010-10-08 17:43:26 +00001533 that don't support __builtin_dwarf_cfa. Furthermore, since
1534 this header file is freestanding, it has to be independent of
1535 config.h, and so the following conditionalisation cannot depend on
1536 configure time checks.
1537
1538 Although it's not clear from
1539 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)',
1540 this expression excludes Darwin.
1541 .cfi directives in Darwin assembly appear to be completely
1542 different and I haven't investigated how they work.
1543
1544 For even more entertainment value, note we have to use the
1545 completely undocumented __builtin_dwarf_cfa(), which appears to
1546 really compute the CFA, whereas __builtin_frame_address(0) claims
1547 to but actually doesn't. See
1548 https://bugs.kde.org/show_bug.cgi?id=243270#c47
sewardjdfa55cf2010-10-06 22:07:06 +00001549*/
sewardj8d1dc152010-10-08 17:43:26 +00001550#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
sewardjdfa55cf2010-10-06 22:07:06 +00001551# define __FRAME_POINTER \
sewardj8d1dc152010-10-08 17:43:26 +00001552 ,"r"(__builtin_dwarf_cfa())
sewardjdfa55cf2010-10-06 22:07:06 +00001553# define VALGRIND_CFI_PROLOGUE \
sewardjdfa55cf2010-10-06 22:07:06 +00001554 "movq %%rbp, %%r15\n\t" \
sewardj8d1dc152010-10-08 17:43:26 +00001555 "movq %2, %%rbp\n\t" \
1556 ".cfi_remember_state\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001557 ".cfi_def_cfa rbp, 0\n\t"
1558# define VALGRIND_CFI_EPILOGUE \
1559 "movq %%r15, %%rbp\n\t" \
1560 ".cfi_restore_state\n\t"
1561#else
1562# define __FRAME_POINTER
1563# define VALGRIND_CFI_PROLOGUE
1564# define VALGRIND_CFI_EPILOGUE
1565#endif
1566
tom4118e0f2012-08-02 09:23:45 +00001567/* Macros to save and align the stack before making a function
1568 call and restore it afterwards as gcc may not keep the stack
1569 pointer aligned if it doesn't realise calls are being made
1570 to other functions. */
1571
1572#define VALGRIND_ALIGN_STACK \
1573 "movq %%rsp,%%r14\n\t" \
1574 "andq $0xfffffffffffffff0,%%rsp\n\t"
1575#define VALGRIND_RESTORE_STACK \
1576 "movq %%r14,%%rsp\n\t"
sewardjdfa55cf2010-10-06 22:07:06 +00001577
sewardj0ec07f32006-01-12 12:32:32 +00001578/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1579 long) == 8. */
1580
sewardja07c2e12007-11-09 23:09:50 +00001581/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1582 macros. In order not to trash the stack redzone, we need to drop
1583 %rsp by 128 before the hidden call, and restore afterwards. The
1584 nastyness is that it is only by luck that the stack still appears
1585 to be unwindable during the hidden call - since then the behaviour
1586 of any routine using this macro does not match what the CFI data
1587 says. Sigh.
1588
1589 Why is this important? Imagine that a wrapper has a stack
1590 allocated local, and passes to the hidden call, a pointer to it.
1591 Because gcc does not know about the hidden call, it may allocate
1592 that local in the redzone. Unfortunately the hidden call may then
1593 trash it before it comes to use it. So we must step clear of the
1594 redzone, for the duration of the hidden call, to make it safe.
1595
1596 Probably the same problem afflicts the other redzone-style ABIs too
sewardj6e9de462011-06-28 07:25:29 +00001597 (ppc64-linux); but for those, the stack is
sewardja07c2e12007-11-09 23:09:50 +00001598 self describing (none of this CFI nonsense) so at least messing
1599 with the stack pointer doesn't give a danger of non-unwindable
1600 stack. */
1601
tom4118e0f2012-08-02 09:23:45 +00001602#define CALL_FN_W_v(lval, orig) \
1603 do { \
1604 volatile OrigFn _orig = (orig); \
1605 volatile unsigned long _argvec[1]; \
1606 volatile unsigned long _res; \
1607 _argvec[0] = (unsigned long)_orig.nraddr; \
1608 __asm__ volatile( \
1609 VALGRIND_CFI_PROLOGUE \
1610 VALGRIND_ALIGN_STACK \
1611 "subq $128,%%rsp\n\t" \
1612 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1613 VALGRIND_CALL_NOREDIR_RAX \
1614 VALGRIND_RESTORE_STACK \
1615 VALGRIND_CFI_EPILOGUE \
1616 : /*out*/ "=a" (_res) \
1617 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1618 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1619 ); \
1620 lval = (__typeof__(lval)) _res; \
sewardj0ec07f32006-01-12 12:32:32 +00001621 } while (0)
1622
tom4118e0f2012-08-02 09:23:45 +00001623#define CALL_FN_W_W(lval, orig, arg1) \
1624 do { \
1625 volatile OrigFn _orig = (orig); \
1626 volatile unsigned long _argvec[2]; \
1627 volatile unsigned long _res; \
1628 _argvec[0] = (unsigned long)_orig.nraddr; \
1629 _argvec[1] = (unsigned long)(arg1); \
1630 __asm__ volatile( \
1631 VALGRIND_CFI_PROLOGUE \
1632 VALGRIND_ALIGN_STACK \
1633 "subq $128,%%rsp\n\t" \
1634 "movq 8(%%rax), %%rdi\n\t" \
1635 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1636 VALGRIND_CALL_NOREDIR_RAX \
1637 VALGRIND_RESTORE_STACK \
1638 VALGRIND_CFI_EPILOGUE \
1639 : /*out*/ "=a" (_res) \
1640 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1641 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1642 ); \
1643 lval = (__typeof__(lval)) _res; \
sewardj0ec07f32006-01-12 12:32:32 +00001644 } while (0)
1645
tom4118e0f2012-08-02 09:23:45 +00001646#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1647 do { \
1648 volatile OrigFn _orig = (orig); \
1649 volatile unsigned long _argvec[3]; \
1650 volatile unsigned long _res; \
1651 _argvec[0] = (unsigned long)_orig.nraddr; \
1652 _argvec[1] = (unsigned long)(arg1); \
1653 _argvec[2] = (unsigned long)(arg2); \
1654 __asm__ volatile( \
1655 VALGRIND_CFI_PROLOGUE \
1656 VALGRIND_ALIGN_STACK \
1657 "subq $128,%%rsp\n\t" \
1658 "movq 16(%%rax), %%rsi\n\t" \
1659 "movq 8(%%rax), %%rdi\n\t" \
1660 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1661 VALGRIND_CALL_NOREDIR_RAX \
1662 VALGRIND_RESTORE_STACK \
1663 VALGRIND_CFI_EPILOGUE \
1664 : /*out*/ "=a" (_res) \
1665 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1666 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1667 ); \
1668 lval = (__typeof__(lval)) _res; \
sewardj0ec07f32006-01-12 12:32:32 +00001669 } while (0)
1670
tom4118e0f2012-08-02 09:23:45 +00001671#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1672 do { \
1673 volatile OrigFn _orig = (orig); \
1674 volatile unsigned long _argvec[4]; \
1675 volatile unsigned long _res; \
1676 _argvec[0] = (unsigned long)_orig.nraddr; \
1677 _argvec[1] = (unsigned long)(arg1); \
1678 _argvec[2] = (unsigned long)(arg2); \
1679 _argvec[3] = (unsigned long)(arg3); \
1680 __asm__ volatile( \
1681 VALGRIND_CFI_PROLOGUE \
1682 VALGRIND_ALIGN_STACK \
1683 "subq $128,%%rsp\n\t" \
1684 "movq 24(%%rax), %%rdx\n\t" \
1685 "movq 16(%%rax), %%rsi\n\t" \
1686 "movq 8(%%rax), %%rdi\n\t" \
1687 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1688 VALGRIND_CALL_NOREDIR_RAX \
1689 VALGRIND_RESTORE_STACK \
1690 VALGRIND_CFI_EPILOGUE \
1691 : /*out*/ "=a" (_res) \
1692 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1693 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1694 ); \
1695 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001696 } while (0)
1697
tom4118e0f2012-08-02 09:23:45 +00001698#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1699 do { \
1700 volatile OrigFn _orig = (orig); \
1701 volatile unsigned long _argvec[5]; \
1702 volatile unsigned long _res; \
1703 _argvec[0] = (unsigned long)_orig.nraddr; \
1704 _argvec[1] = (unsigned long)(arg1); \
1705 _argvec[2] = (unsigned long)(arg2); \
1706 _argvec[3] = (unsigned long)(arg3); \
1707 _argvec[4] = (unsigned long)(arg4); \
1708 __asm__ volatile( \
1709 VALGRIND_CFI_PROLOGUE \
1710 VALGRIND_ALIGN_STACK \
1711 "subq $128,%%rsp\n\t" \
1712 "movq 32(%%rax), %%rcx\n\t" \
1713 "movq 24(%%rax), %%rdx\n\t" \
1714 "movq 16(%%rax), %%rsi\n\t" \
1715 "movq 8(%%rax), %%rdi\n\t" \
1716 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1717 VALGRIND_CALL_NOREDIR_RAX \
1718 VALGRIND_RESTORE_STACK \
1719 VALGRIND_CFI_EPILOGUE \
1720 : /*out*/ "=a" (_res) \
1721 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1722 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1723 ); \
1724 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001725 } while (0)
1726
tom4118e0f2012-08-02 09:23:45 +00001727#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1728 do { \
1729 volatile OrigFn _orig = (orig); \
1730 volatile unsigned long _argvec[6]; \
1731 volatile unsigned long _res; \
1732 _argvec[0] = (unsigned long)_orig.nraddr; \
1733 _argvec[1] = (unsigned long)(arg1); \
1734 _argvec[2] = (unsigned long)(arg2); \
1735 _argvec[3] = (unsigned long)(arg3); \
1736 _argvec[4] = (unsigned long)(arg4); \
1737 _argvec[5] = (unsigned long)(arg5); \
1738 __asm__ volatile( \
1739 VALGRIND_CFI_PROLOGUE \
1740 VALGRIND_ALIGN_STACK \
1741 "subq $128,%%rsp\n\t" \
1742 "movq 40(%%rax), %%r8\n\t" \
1743 "movq 32(%%rax), %%rcx\n\t" \
1744 "movq 24(%%rax), %%rdx\n\t" \
1745 "movq 16(%%rax), %%rsi\n\t" \
1746 "movq 8(%%rax), %%rdi\n\t" \
1747 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1748 VALGRIND_CALL_NOREDIR_RAX \
1749 VALGRIND_RESTORE_STACK \
1750 VALGRIND_CFI_EPILOGUE \
1751 : /*out*/ "=a" (_res) \
1752 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1753 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1754 ); \
1755 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001756 } while (0)
1757
tom4118e0f2012-08-02 09:23:45 +00001758#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1759 do { \
1760 volatile OrigFn _orig = (orig); \
1761 volatile unsigned long _argvec[7]; \
1762 volatile unsigned long _res; \
1763 _argvec[0] = (unsigned long)_orig.nraddr; \
1764 _argvec[1] = (unsigned long)(arg1); \
1765 _argvec[2] = (unsigned long)(arg2); \
1766 _argvec[3] = (unsigned long)(arg3); \
1767 _argvec[4] = (unsigned long)(arg4); \
1768 _argvec[5] = (unsigned long)(arg5); \
1769 _argvec[6] = (unsigned long)(arg6); \
1770 __asm__ volatile( \
1771 VALGRIND_CFI_PROLOGUE \
1772 VALGRIND_ALIGN_STACK \
1773 "subq $128,%%rsp\n\t" \
1774 "movq 48(%%rax), %%r9\n\t" \
1775 "movq 40(%%rax), %%r8\n\t" \
1776 "movq 32(%%rax), %%rcx\n\t" \
1777 "movq 24(%%rax), %%rdx\n\t" \
1778 "movq 16(%%rax), %%rsi\n\t" \
1779 "movq 8(%%rax), %%rdi\n\t" \
1780 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1781 VALGRIND_CALL_NOREDIR_RAX \
1782 VALGRIND_RESTORE_STACK \
1783 VALGRIND_CFI_EPILOGUE \
1784 : /*out*/ "=a" (_res) \
1785 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1786 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1787 ); \
1788 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001789 } while (0)
1790
tom4118e0f2012-08-02 09:23:45 +00001791#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1792 arg7) \
1793 do { \
1794 volatile OrigFn _orig = (orig); \
1795 volatile unsigned long _argvec[8]; \
1796 volatile unsigned long _res; \
1797 _argvec[0] = (unsigned long)_orig.nraddr; \
1798 _argvec[1] = (unsigned long)(arg1); \
1799 _argvec[2] = (unsigned long)(arg2); \
1800 _argvec[3] = (unsigned long)(arg3); \
1801 _argvec[4] = (unsigned long)(arg4); \
1802 _argvec[5] = (unsigned long)(arg5); \
1803 _argvec[6] = (unsigned long)(arg6); \
1804 _argvec[7] = (unsigned long)(arg7); \
1805 __asm__ volatile( \
1806 VALGRIND_CFI_PROLOGUE \
1807 VALGRIND_ALIGN_STACK \
1808 "subq $136,%%rsp\n\t" \
1809 "pushq 56(%%rax)\n\t" \
1810 "movq 48(%%rax), %%r9\n\t" \
1811 "movq 40(%%rax), %%r8\n\t" \
1812 "movq 32(%%rax), %%rcx\n\t" \
1813 "movq 24(%%rax), %%rdx\n\t" \
1814 "movq 16(%%rax), %%rsi\n\t" \
1815 "movq 8(%%rax), %%rdi\n\t" \
1816 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1817 VALGRIND_CALL_NOREDIR_RAX \
1818 VALGRIND_RESTORE_STACK \
1819 VALGRIND_CFI_EPILOGUE \
1820 : /*out*/ "=a" (_res) \
1821 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1822 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1823 ); \
1824 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001825 } while (0)
1826
tom4118e0f2012-08-02 09:23:45 +00001827#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1828 arg7,arg8) \
1829 do { \
1830 volatile OrigFn _orig = (orig); \
1831 volatile unsigned long _argvec[9]; \
1832 volatile unsigned long _res; \
1833 _argvec[0] = (unsigned long)_orig.nraddr; \
1834 _argvec[1] = (unsigned long)(arg1); \
1835 _argvec[2] = (unsigned long)(arg2); \
1836 _argvec[3] = (unsigned long)(arg3); \
1837 _argvec[4] = (unsigned long)(arg4); \
1838 _argvec[5] = (unsigned long)(arg5); \
1839 _argvec[6] = (unsigned long)(arg6); \
1840 _argvec[7] = (unsigned long)(arg7); \
1841 _argvec[8] = (unsigned long)(arg8); \
1842 __asm__ volatile( \
1843 VALGRIND_CFI_PROLOGUE \
1844 VALGRIND_ALIGN_STACK \
1845 "subq $128,%%rsp\n\t" \
1846 "pushq 64(%%rax)\n\t" \
1847 "pushq 56(%%rax)\n\t" \
1848 "movq 48(%%rax), %%r9\n\t" \
1849 "movq 40(%%rax), %%r8\n\t" \
1850 "movq 32(%%rax), %%rcx\n\t" \
1851 "movq 24(%%rax), %%rdx\n\t" \
1852 "movq 16(%%rax), %%rsi\n\t" \
1853 "movq 8(%%rax), %%rdi\n\t" \
1854 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1855 VALGRIND_CALL_NOREDIR_RAX \
1856 VALGRIND_RESTORE_STACK \
1857 VALGRIND_CFI_EPILOGUE \
1858 : /*out*/ "=a" (_res) \
1859 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1860 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1861 ); \
1862 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001863 } while (0)
1864
tom4118e0f2012-08-02 09:23:45 +00001865#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1866 arg7,arg8,arg9) \
1867 do { \
1868 volatile OrigFn _orig = (orig); \
1869 volatile unsigned long _argvec[10]; \
1870 volatile unsigned long _res; \
1871 _argvec[0] = (unsigned long)_orig.nraddr; \
1872 _argvec[1] = (unsigned long)(arg1); \
1873 _argvec[2] = (unsigned long)(arg2); \
1874 _argvec[3] = (unsigned long)(arg3); \
1875 _argvec[4] = (unsigned long)(arg4); \
1876 _argvec[5] = (unsigned long)(arg5); \
1877 _argvec[6] = (unsigned long)(arg6); \
1878 _argvec[7] = (unsigned long)(arg7); \
1879 _argvec[8] = (unsigned long)(arg8); \
1880 _argvec[9] = (unsigned long)(arg9); \
1881 __asm__ volatile( \
1882 VALGRIND_CFI_PROLOGUE \
1883 VALGRIND_ALIGN_STACK \
1884 "subq $136,%%rsp\n\t" \
1885 "pushq 72(%%rax)\n\t" \
1886 "pushq 64(%%rax)\n\t" \
1887 "pushq 56(%%rax)\n\t" \
1888 "movq 48(%%rax), %%r9\n\t" \
1889 "movq 40(%%rax), %%r8\n\t" \
1890 "movq 32(%%rax), %%rcx\n\t" \
1891 "movq 24(%%rax), %%rdx\n\t" \
1892 "movq 16(%%rax), %%rsi\n\t" \
1893 "movq 8(%%rax), %%rdi\n\t" \
1894 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1895 VALGRIND_CALL_NOREDIR_RAX \
1896 VALGRIND_RESTORE_STACK \
1897 VALGRIND_CFI_EPILOGUE \
1898 : /*out*/ "=a" (_res) \
1899 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1900 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1901 ); \
1902 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001903 } while (0)
1904
tom4118e0f2012-08-02 09:23:45 +00001905#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1906 arg7,arg8,arg9,arg10) \
1907 do { \
1908 volatile OrigFn _orig = (orig); \
1909 volatile unsigned long _argvec[11]; \
1910 volatile unsigned long _res; \
1911 _argvec[0] = (unsigned long)_orig.nraddr; \
1912 _argvec[1] = (unsigned long)(arg1); \
1913 _argvec[2] = (unsigned long)(arg2); \
1914 _argvec[3] = (unsigned long)(arg3); \
1915 _argvec[4] = (unsigned long)(arg4); \
1916 _argvec[5] = (unsigned long)(arg5); \
1917 _argvec[6] = (unsigned long)(arg6); \
1918 _argvec[7] = (unsigned long)(arg7); \
1919 _argvec[8] = (unsigned long)(arg8); \
1920 _argvec[9] = (unsigned long)(arg9); \
1921 _argvec[10] = (unsigned long)(arg10); \
1922 __asm__ volatile( \
1923 VALGRIND_CFI_PROLOGUE \
1924 VALGRIND_ALIGN_STACK \
1925 "subq $128,%%rsp\n\t" \
1926 "pushq 80(%%rax)\n\t" \
1927 "pushq 72(%%rax)\n\t" \
1928 "pushq 64(%%rax)\n\t" \
1929 "pushq 56(%%rax)\n\t" \
1930 "movq 48(%%rax), %%r9\n\t" \
1931 "movq 40(%%rax), %%r8\n\t" \
1932 "movq 32(%%rax), %%rcx\n\t" \
1933 "movq 24(%%rax), %%rdx\n\t" \
1934 "movq 16(%%rax), %%rsi\n\t" \
1935 "movq 8(%%rax), %%rdi\n\t" \
1936 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1937 VALGRIND_CALL_NOREDIR_RAX \
1938 VALGRIND_RESTORE_STACK \
1939 VALGRIND_CFI_EPILOGUE \
1940 : /*out*/ "=a" (_res) \
1941 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1942 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1943 ); \
1944 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001945 } while (0)
1946
tom4118e0f2012-08-02 09:23:45 +00001947#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1948 arg7,arg8,arg9,arg10,arg11) \
1949 do { \
1950 volatile OrigFn _orig = (orig); \
1951 volatile unsigned long _argvec[12]; \
1952 volatile unsigned long _res; \
1953 _argvec[0] = (unsigned long)_orig.nraddr; \
1954 _argvec[1] = (unsigned long)(arg1); \
1955 _argvec[2] = (unsigned long)(arg2); \
1956 _argvec[3] = (unsigned long)(arg3); \
1957 _argvec[4] = (unsigned long)(arg4); \
1958 _argvec[5] = (unsigned long)(arg5); \
1959 _argvec[6] = (unsigned long)(arg6); \
1960 _argvec[7] = (unsigned long)(arg7); \
1961 _argvec[8] = (unsigned long)(arg8); \
1962 _argvec[9] = (unsigned long)(arg9); \
1963 _argvec[10] = (unsigned long)(arg10); \
1964 _argvec[11] = (unsigned long)(arg11); \
1965 __asm__ volatile( \
1966 VALGRIND_CFI_PROLOGUE \
1967 VALGRIND_ALIGN_STACK \
1968 "subq $136,%%rsp\n\t" \
1969 "pushq 88(%%rax)\n\t" \
1970 "pushq 80(%%rax)\n\t" \
1971 "pushq 72(%%rax)\n\t" \
1972 "pushq 64(%%rax)\n\t" \
1973 "pushq 56(%%rax)\n\t" \
1974 "movq 48(%%rax), %%r9\n\t" \
1975 "movq 40(%%rax), %%r8\n\t" \
1976 "movq 32(%%rax), %%rcx\n\t" \
1977 "movq 24(%%rax), %%rdx\n\t" \
1978 "movq 16(%%rax), %%rsi\n\t" \
1979 "movq 8(%%rax), %%rdi\n\t" \
1980 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1981 VALGRIND_CALL_NOREDIR_RAX \
1982 VALGRIND_RESTORE_STACK \
1983 VALGRIND_CFI_EPILOGUE \
1984 : /*out*/ "=a" (_res) \
1985 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1986 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1987 ); \
1988 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001989 } while (0)
1990
tom4118e0f2012-08-02 09:23:45 +00001991#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1992 arg7,arg8,arg9,arg10,arg11,arg12) \
1993 do { \
1994 volatile OrigFn _orig = (orig); \
1995 volatile unsigned long _argvec[13]; \
1996 volatile unsigned long _res; \
1997 _argvec[0] = (unsigned long)_orig.nraddr; \
1998 _argvec[1] = (unsigned long)(arg1); \
1999 _argvec[2] = (unsigned long)(arg2); \
2000 _argvec[3] = (unsigned long)(arg3); \
2001 _argvec[4] = (unsigned long)(arg4); \
2002 _argvec[5] = (unsigned long)(arg5); \
2003 _argvec[6] = (unsigned long)(arg6); \
2004 _argvec[7] = (unsigned long)(arg7); \
2005 _argvec[8] = (unsigned long)(arg8); \
2006 _argvec[9] = (unsigned long)(arg9); \
2007 _argvec[10] = (unsigned long)(arg10); \
2008 _argvec[11] = (unsigned long)(arg11); \
2009 _argvec[12] = (unsigned long)(arg12); \
2010 __asm__ volatile( \
2011 VALGRIND_CFI_PROLOGUE \
2012 VALGRIND_ALIGN_STACK \
2013 "subq $128,%%rsp\n\t" \
2014 "pushq 96(%%rax)\n\t" \
2015 "pushq 88(%%rax)\n\t" \
2016 "pushq 80(%%rax)\n\t" \
2017 "pushq 72(%%rax)\n\t" \
2018 "pushq 64(%%rax)\n\t" \
2019 "pushq 56(%%rax)\n\t" \
2020 "movq 48(%%rax), %%r9\n\t" \
2021 "movq 40(%%rax), %%r8\n\t" \
2022 "movq 32(%%rax), %%rcx\n\t" \
2023 "movq 24(%%rax), %%rdx\n\t" \
2024 "movq 16(%%rax), %%rsi\n\t" \
2025 "movq 8(%%rax), %%rdi\n\t" \
2026 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
2027 VALGRIND_CALL_NOREDIR_RAX \
2028 VALGRIND_RESTORE_STACK \
2029 VALGRIND_CFI_EPILOGUE \
2030 : /*out*/ "=a" (_res) \
2031 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
2032 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2033 ); \
2034 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00002035 } while (0)
2036
njnf76d27a2009-05-28 01:53:07 +00002037#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00002038
sewardjf5c1a7f2006-10-17 01:32:48 +00002039/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002040
sewardjf5c1a7f2006-10-17 01:32:48 +00002041#if defined(PLAT_ppc32_linux)
sewardj0ec07f32006-01-12 12:32:32 +00002042
sewardjead61df2006-03-12 13:39:15 +00002043/* This is useful for finding out about the on-stack stuff:
2044
2045 extern int f9 ( int,int,int,int,int,int,int,int,int );
2046 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
2047 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
2048 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
2049
2050 int g9 ( void ) {
2051 return f9(11,22,33,44,55,66,77,88,99);
2052 }
2053 int g10 ( void ) {
2054 return f10(11,22,33,44,55,66,77,88,99,110);
2055 }
2056 int g11 ( void ) {
2057 return f11(11,22,33,44,55,66,77,88,99,110,121);
2058 }
2059 int g12 ( void ) {
2060 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
2061 }
2062*/
2063
sewardj0ec07f32006-01-12 12:32:32 +00002064/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2065
2066/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00002067#define __CALLER_SAVED_REGS \
2068 "lr", "ctr", "xer", \
2069 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2070 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2071 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00002072
tom4118e0f2012-08-02 09:23:45 +00002073/* Macros to save and align the stack before making a function
2074 call and restore it afterwards as gcc may not keep the stack
2075 pointer aligned if it doesn't realise calls are being made
2076 to other functions. */
2077
2078#define VALGRIND_ALIGN_STACK \
2079 "mr 28,1\n\t" \
2080 "rlwinm 1,1,0,0,27\n\t"
2081#define VALGRIND_RESTORE_STACK \
2082 "mr 1,28\n\t"
2083
sewardjead61df2006-03-12 13:39:15 +00002084/* These CALL_FN_ macros assume that on ppc32-linux,
2085 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00002086
sewardj38de0992006-01-20 16:46:34 +00002087#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00002088 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002089 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00002090 volatile unsigned long _argvec[1]; \
2091 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002092 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00002093 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002094 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002095 "mr 11,%1\n\t" \
2096 "lwz 11,0(11)\n\t" /* target->r11 */ \
2097 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002098 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002099 "mr %0,3" \
2100 : /*out*/ "=r" (_res) \
2101 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002102 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj0ec07f32006-01-12 12:32:32 +00002103 ); \
2104 lval = (__typeof__(lval)) _res; \
2105 } while (0)
2106
sewardj38de0992006-01-20 16:46:34 +00002107#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00002108 do { \
sewardj38de0992006-01-20 16:46:34 +00002109 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00002110 volatile unsigned long _argvec[2]; \
2111 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00002112 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00002113 _argvec[1] = (unsigned long)arg1; \
2114 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002115 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002116 "mr 11,%1\n\t" \
2117 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2118 "lwz 11,0(11)\n\t" /* target->r11 */ \
2119 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002120 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002121 "mr %0,3" \
2122 : /*out*/ "=r" (_res) \
2123 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002124 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj0ec07f32006-01-12 12:32:32 +00002125 ); \
2126 lval = (__typeof__(lval)) _res; \
2127 } while (0)
2128
sewardj38de0992006-01-20 16:46:34 +00002129#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00002130 do { \
sewardj38de0992006-01-20 16:46:34 +00002131 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00002132 volatile unsigned long _argvec[3]; \
2133 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00002134 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00002135 _argvec[1] = (unsigned long)arg1; \
2136 _argvec[2] = (unsigned long)arg2; \
2137 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002138 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002139 "mr 11,%1\n\t" \
2140 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2141 "lwz 4,8(11)\n\t" \
2142 "lwz 11,0(11)\n\t" /* target->r11 */ \
2143 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002144 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002145 "mr %0,3" \
2146 : /*out*/ "=r" (_res) \
2147 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002148 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj0ec07f32006-01-12 12:32:32 +00002149 ); \
2150 lval = (__typeof__(lval)) _res; \
2151 } while (0)
2152
sewardjead61df2006-03-12 13:39:15 +00002153#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2154 do { \
2155 volatile OrigFn _orig = (orig); \
2156 volatile unsigned long _argvec[4]; \
2157 volatile unsigned long _res; \
2158 _argvec[0] = (unsigned long)_orig.nraddr; \
2159 _argvec[1] = (unsigned long)arg1; \
2160 _argvec[2] = (unsigned long)arg2; \
2161 _argvec[3] = (unsigned long)arg3; \
2162 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002163 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002164 "mr 11,%1\n\t" \
2165 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2166 "lwz 4,8(11)\n\t" \
2167 "lwz 5,12(11)\n\t" \
2168 "lwz 11,0(11)\n\t" /* target->r11 */ \
2169 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002170 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002171 "mr %0,3" \
2172 : /*out*/ "=r" (_res) \
2173 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002174 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002175 ); \
2176 lval = (__typeof__(lval)) _res; \
2177 } while (0)
2178
2179#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2180 do { \
2181 volatile OrigFn _orig = (orig); \
2182 volatile unsigned long _argvec[5]; \
2183 volatile unsigned long _res; \
2184 _argvec[0] = (unsigned long)_orig.nraddr; \
2185 _argvec[1] = (unsigned long)arg1; \
2186 _argvec[2] = (unsigned long)arg2; \
2187 _argvec[3] = (unsigned long)arg3; \
2188 _argvec[4] = (unsigned long)arg4; \
2189 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002190 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002191 "mr 11,%1\n\t" \
2192 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2193 "lwz 4,8(11)\n\t" \
2194 "lwz 5,12(11)\n\t" \
2195 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2196 "lwz 11,0(11)\n\t" /* target->r11 */ \
2197 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002198 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002199 "mr %0,3" \
2200 : /*out*/ "=r" (_res) \
2201 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002202 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002203 ); \
2204 lval = (__typeof__(lval)) _res; \
2205 } while (0)
2206
2207#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2208 do { \
2209 volatile OrigFn _orig = (orig); \
2210 volatile unsigned long _argvec[6]; \
2211 volatile unsigned long _res; \
2212 _argvec[0] = (unsigned long)_orig.nraddr; \
2213 _argvec[1] = (unsigned long)arg1; \
2214 _argvec[2] = (unsigned long)arg2; \
2215 _argvec[3] = (unsigned long)arg3; \
2216 _argvec[4] = (unsigned long)arg4; \
2217 _argvec[5] = (unsigned long)arg5; \
2218 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002219 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002220 "mr 11,%1\n\t" \
2221 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2222 "lwz 4,8(11)\n\t" \
2223 "lwz 5,12(11)\n\t" \
2224 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2225 "lwz 7,20(11)\n\t" \
2226 "lwz 11,0(11)\n\t" /* target->r11 */ \
2227 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002228 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002229 "mr %0,3" \
2230 : /*out*/ "=r" (_res) \
2231 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002232 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002233 ); \
2234 lval = (__typeof__(lval)) _res; \
2235 } while (0)
2236
2237#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2238 do { \
2239 volatile OrigFn _orig = (orig); \
2240 volatile unsigned long _argvec[7]; \
2241 volatile unsigned long _res; \
2242 _argvec[0] = (unsigned long)_orig.nraddr; \
2243 _argvec[1] = (unsigned long)arg1; \
2244 _argvec[2] = (unsigned long)arg2; \
2245 _argvec[3] = (unsigned long)arg3; \
2246 _argvec[4] = (unsigned long)arg4; \
2247 _argvec[5] = (unsigned long)arg5; \
2248 _argvec[6] = (unsigned long)arg6; \
2249 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002250 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002251 "mr 11,%1\n\t" \
2252 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2253 "lwz 4,8(11)\n\t" \
2254 "lwz 5,12(11)\n\t" \
2255 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2256 "lwz 7,20(11)\n\t" \
2257 "lwz 8,24(11)\n\t" \
2258 "lwz 11,0(11)\n\t" /* target->r11 */ \
2259 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002260 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002261 "mr %0,3" \
2262 : /*out*/ "=r" (_res) \
2263 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002264 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002265 ); \
2266 lval = (__typeof__(lval)) _res; \
2267 } while (0)
2268
2269#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2270 arg7) \
2271 do { \
2272 volatile OrigFn _orig = (orig); \
2273 volatile unsigned long _argvec[8]; \
2274 volatile unsigned long _res; \
2275 _argvec[0] = (unsigned long)_orig.nraddr; \
2276 _argvec[1] = (unsigned long)arg1; \
2277 _argvec[2] = (unsigned long)arg2; \
2278 _argvec[3] = (unsigned long)arg3; \
2279 _argvec[4] = (unsigned long)arg4; \
2280 _argvec[5] = (unsigned long)arg5; \
2281 _argvec[6] = (unsigned long)arg6; \
2282 _argvec[7] = (unsigned long)arg7; \
2283 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002284 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002285 "mr 11,%1\n\t" \
2286 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2287 "lwz 4,8(11)\n\t" \
2288 "lwz 5,12(11)\n\t" \
2289 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2290 "lwz 7,20(11)\n\t" \
2291 "lwz 8,24(11)\n\t" \
2292 "lwz 9,28(11)\n\t" \
2293 "lwz 11,0(11)\n\t" /* target->r11 */ \
2294 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002295 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002296 "mr %0,3" \
2297 : /*out*/ "=r" (_res) \
2298 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002299 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002300 ); \
2301 lval = (__typeof__(lval)) _res; \
2302 } while (0)
2303
2304#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2305 arg7,arg8) \
2306 do { \
2307 volatile OrigFn _orig = (orig); \
2308 volatile unsigned long _argvec[9]; \
2309 volatile unsigned long _res; \
2310 _argvec[0] = (unsigned long)_orig.nraddr; \
2311 _argvec[1] = (unsigned long)arg1; \
2312 _argvec[2] = (unsigned long)arg2; \
2313 _argvec[3] = (unsigned long)arg3; \
2314 _argvec[4] = (unsigned long)arg4; \
2315 _argvec[5] = (unsigned long)arg5; \
2316 _argvec[6] = (unsigned long)arg6; \
2317 _argvec[7] = (unsigned long)arg7; \
2318 _argvec[8] = (unsigned long)arg8; \
2319 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002320 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002321 "mr 11,%1\n\t" \
2322 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2323 "lwz 4,8(11)\n\t" \
2324 "lwz 5,12(11)\n\t" \
2325 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2326 "lwz 7,20(11)\n\t" \
2327 "lwz 8,24(11)\n\t" \
2328 "lwz 9,28(11)\n\t" \
2329 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2330 "lwz 11,0(11)\n\t" /* target->r11 */ \
2331 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002332 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002333 "mr %0,3" \
2334 : /*out*/ "=r" (_res) \
2335 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002336 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002337 ); \
2338 lval = (__typeof__(lval)) _res; \
2339 } while (0)
2340
2341#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2342 arg7,arg8,arg9) \
2343 do { \
2344 volatile OrigFn _orig = (orig); \
2345 volatile unsigned long _argvec[10]; \
2346 volatile unsigned long _res; \
2347 _argvec[0] = (unsigned long)_orig.nraddr; \
2348 _argvec[1] = (unsigned long)arg1; \
2349 _argvec[2] = (unsigned long)arg2; \
2350 _argvec[3] = (unsigned long)arg3; \
2351 _argvec[4] = (unsigned long)arg4; \
2352 _argvec[5] = (unsigned long)arg5; \
2353 _argvec[6] = (unsigned long)arg6; \
2354 _argvec[7] = (unsigned long)arg7; \
2355 _argvec[8] = (unsigned long)arg8; \
2356 _argvec[9] = (unsigned long)arg9; \
2357 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002358 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002359 "mr 11,%1\n\t" \
2360 "addi 1,1,-16\n\t" \
2361 /* arg9 */ \
2362 "lwz 3,36(11)\n\t" \
2363 "stw 3,8(1)\n\t" \
2364 /* args1-8 */ \
2365 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2366 "lwz 4,8(11)\n\t" \
2367 "lwz 5,12(11)\n\t" \
2368 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2369 "lwz 7,20(11)\n\t" \
2370 "lwz 8,24(11)\n\t" \
2371 "lwz 9,28(11)\n\t" \
2372 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2373 "lwz 11,0(11)\n\t" /* target->r11 */ \
2374 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002375 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002376 "mr %0,3" \
2377 : /*out*/ "=r" (_res) \
2378 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002379 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002380 ); \
2381 lval = (__typeof__(lval)) _res; \
2382 } while (0)
2383
2384#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2385 arg7,arg8,arg9,arg10) \
2386 do { \
2387 volatile OrigFn _orig = (orig); \
2388 volatile unsigned long _argvec[11]; \
2389 volatile unsigned long _res; \
2390 _argvec[0] = (unsigned long)_orig.nraddr; \
2391 _argvec[1] = (unsigned long)arg1; \
2392 _argvec[2] = (unsigned long)arg2; \
2393 _argvec[3] = (unsigned long)arg3; \
2394 _argvec[4] = (unsigned long)arg4; \
2395 _argvec[5] = (unsigned long)arg5; \
2396 _argvec[6] = (unsigned long)arg6; \
2397 _argvec[7] = (unsigned long)arg7; \
2398 _argvec[8] = (unsigned long)arg8; \
2399 _argvec[9] = (unsigned long)arg9; \
2400 _argvec[10] = (unsigned long)arg10; \
2401 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002402 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002403 "mr 11,%1\n\t" \
2404 "addi 1,1,-16\n\t" \
2405 /* arg10 */ \
2406 "lwz 3,40(11)\n\t" \
2407 "stw 3,12(1)\n\t" \
2408 /* arg9 */ \
2409 "lwz 3,36(11)\n\t" \
2410 "stw 3,8(1)\n\t" \
2411 /* args1-8 */ \
2412 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2413 "lwz 4,8(11)\n\t" \
2414 "lwz 5,12(11)\n\t" \
2415 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2416 "lwz 7,20(11)\n\t" \
2417 "lwz 8,24(11)\n\t" \
2418 "lwz 9,28(11)\n\t" \
2419 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2420 "lwz 11,0(11)\n\t" /* target->r11 */ \
2421 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002422 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002423 "mr %0,3" \
2424 : /*out*/ "=r" (_res) \
2425 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002426 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002427 ); \
2428 lval = (__typeof__(lval)) _res; \
2429 } while (0)
2430
2431#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2432 arg7,arg8,arg9,arg10,arg11) \
2433 do { \
2434 volatile OrigFn _orig = (orig); \
2435 volatile unsigned long _argvec[12]; \
2436 volatile unsigned long _res; \
2437 _argvec[0] = (unsigned long)_orig.nraddr; \
2438 _argvec[1] = (unsigned long)arg1; \
2439 _argvec[2] = (unsigned long)arg2; \
2440 _argvec[3] = (unsigned long)arg3; \
2441 _argvec[4] = (unsigned long)arg4; \
2442 _argvec[5] = (unsigned long)arg5; \
2443 _argvec[6] = (unsigned long)arg6; \
2444 _argvec[7] = (unsigned long)arg7; \
2445 _argvec[8] = (unsigned long)arg8; \
2446 _argvec[9] = (unsigned long)arg9; \
2447 _argvec[10] = (unsigned long)arg10; \
2448 _argvec[11] = (unsigned long)arg11; \
2449 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002450 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002451 "mr 11,%1\n\t" \
2452 "addi 1,1,-32\n\t" \
2453 /* arg11 */ \
2454 "lwz 3,44(11)\n\t" \
2455 "stw 3,16(1)\n\t" \
2456 /* arg10 */ \
2457 "lwz 3,40(11)\n\t" \
2458 "stw 3,12(1)\n\t" \
2459 /* arg9 */ \
2460 "lwz 3,36(11)\n\t" \
2461 "stw 3,8(1)\n\t" \
2462 /* args1-8 */ \
2463 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2464 "lwz 4,8(11)\n\t" \
2465 "lwz 5,12(11)\n\t" \
2466 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2467 "lwz 7,20(11)\n\t" \
2468 "lwz 8,24(11)\n\t" \
2469 "lwz 9,28(11)\n\t" \
2470 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2471 "lwz 11,0(11)\n\t" /* target->r11 */ \
2472 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002473 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002474 "mr %0,3" \
2475 : /*out*/ "=r" (_res) \
2476 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002477 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002478 ); \
2479 lval = (__typeof__(lval)) _res; \
2480 } while (0)
2481
2482#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2483 arg7,arg8,arg9,arg10,arg11,arg12) \
2484 do { \
2485 volatile OrigFn _orig = (orig); \
2486 volatile unsigned long _argvec[13]; \
2487 volatile unsigned long _res; \
2488 _argvec[0] = (unsigned long)_orig.nraddr; \
2489 _argvec[1] = (unsigned long)arg1; \
2490 _argvec[2] = (unsigned long)arg2; \
2491 _argvec[3] = (unsigned long)arg3; \
2492 _argvec[4] = (unsigned long)arg4; \
2493 _argvec[5] = (unsigned long)arg5; \
2494 _argvec[6] = (unsigned long)arg6; \
2495 _argvec[7] = (unsigned long)arg7; \
2496 _argvec[8] = (unsigned long)arg8; \
2497 _argvec[9] = (unsigned long)arg9; \
2498 _argvec[10] = (unsigned long)arg10; \
2499 _argvec[11] = (unsigned long)arg11; \
2500 _argvec[12] = (unsigned long)arg12; \
2501 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002502 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002503 "mr 11,%1\n\t" \
2504 "addi 1,1,-32\n\t" \
2505 /* arg12 */ \
2506 "lwz 3,48(11)\n\t" \
2507 "stw 3,20(1)\n\t" \
2508 /* arg11 */ \
2509 "lwz 3,44(11)\n\t" \
2510 "stw 3,16(1)\n\t" \
2511 /* arg10 */ \
2512 "lwz 3,40(11)\n\t" \
2513 "stw 3,12(1)\n\t" \
2514 /* arg9 */ \
2515 "lwz 3,36(11)\n\t" \
2516 "stw 3,8(1)\n\t" \
2517 /* args1-8 */ \
2518 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2519 "lwz 4,8(11)\n\t" \
2520 "lwz 5,12(11)\n\t" \
2521 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2522 "lwz 7,20(11)\n\t" \
2523 "lwz 8,24(11)\n\t" \
2524 "lwz 9,28(11)\n\t" \
2525 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2526 "lwz 11,0(11)\n\t" /* target->r11 */ \
2527 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002528 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002529 "mr %0,3" \
2530 : /*out*/ "=r" (_res) \
2531 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002532 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002533 ); \
2534 lval = (__typeof__(lval)) _res; \
2535 } while (0)
2536
sewardjf5c1a7f2006-10-17 01:32:48 +00002537#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +00002538
sewardjf5c1a7f2006-10-17 01:32:48 +00002539/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002540
carllcae0cc22014-08-07 23:17:29 +00002541#if defined(PLAT_ppc64be_linux)
sewardj9734b202006-01-17 01:49:37 +00002542
2543/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2544
2545/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00002546#define __CALLER_SAVED_REGS \
2547 "lr", "ctr", "xer", \
2548 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2549 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2550 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00002551
tom4118e0f2012-08-02 09:23:45 +00002552/* Macros to save and align the stack before making a function
2553 call and restore it afterwards as gcc may not keep the stack
2554 pointer aligned if it doesn't realise calls are being made
2555 to other functions. */
2556
2557#define VALGRIND_ALIGN_STACK \
2558 "mr 28,1\n\t" \
2559 "rldicr 1,1,0,59\n\t"
2560#define VALGRIND_RESTORE_STACK \
2561 "mr 1,28\n\t"
2562
sewardj9734b202006-01-17 01:49:37 +00002563/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2564 long) == 8. */
2565
sewardjd68ac3e2006-01-20 14:31:57 +00002566#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00002567 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002568 volatile OrigFn _orig = (orig); \
2569 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00002570 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002571 /* _argvec[0] holds current r2 across the call */ \
2572 _argvec[1] = (unsigned long)_orig.r2; \
2573 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00002574 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002575 VALGRIND_ALIGN_STACK \
sewardj9734b202006-01-17 01:49:37 +00002576 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002577 "std 2,-16(11)\n\t" /* save tocptr */ \
2578 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2579 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002580 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2581 "mr 11,%1\n\t" \
2582 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002583 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2584 VALGRIND_RESTORE_STACK \
sewardj9734b202006-01-17 01:49:37 +00002585 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002586 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002587 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj9734b202006-01-17 01:49:37 +00002588 ); \
2589 lval = (__typeof__(lval)) _res; \
2590 } while (0)
2591
sewardjd68ac3e2006-01-20 14:31:57 +00002592#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00002593 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002594 volatile OrigFn _orig = (orig); \
2595 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00002596 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002597 /* _argvec[0] holds current r2 across the call */ \
2598 _argvec[1] = (unsigned long)_orig.r2; \
2599 _argvec[2] = (unsigned long)_orig.nraddr; \
2600 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00002601 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002602 VALGRIND_ALIGN_STACK \
sewardj9734b202006-01-17 01:49:37 +00002603 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002604 "std 2,-16(11)\n\t" /* save tocptr */ \
2605 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2606 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2607 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002608 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2609 "mr 11,%1\n\t" \
2610 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002611 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2612 VALGRIND_RESTORE_STACK \
sewardj9734b202006-01-17 01:49:37 +00002613 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002614 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002615 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj9734b202006-01-17 01:49:37 +00002616 ); \
2617 lval = (__typeof__(lval)) _res; \
2618 } while (0)
2619
sewardjd68ac3e2006-01-20 14:31:57 +00002620#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00002621 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002622 volatile OrigFn _orig = (orig); \
2623 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00002624 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002625 /* _argvec[0] holds current r2 across the call */ \
2626 _argvec[1] = (unsigned long)_orig.r2; \
2627 _argvec[2] = (unsigned long)_orig.nraddr; \
2628 _argvec[2+1] = (unsigned long)arg1; \
2629 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00002630 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002631 VALGRIND_ALIGN_STACK \
sewardj9734b202006-01-17 01:49:37 +00002632 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002633 "std 2,-16(11)\n\t" /* save tocptr */ \
2634 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2635 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00002636 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00002637 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002638 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2639 "mr 11,%1\n\t" \
2640 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002641 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2642 VALGRIND_RESTORE_STACK \
sewardj9734b202006-01-17 01:49:37 +00002643 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002644 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002645 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj9734b202006-01-17 01:49:37 +00002646 ); \
2647 lval = (__typeof__(lval)) _res; \
2648 } while (0)
2649
sewardjcd636392006-03-12 16:48:14 +00002650#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2651 do { \
2652 volatile OrigFn _orig = (orig); \
2653 volatile unsigned long _argvec[3+3]; \
2654 volatile unsigned long _res; \
2655 /* _argvec[0] holds current r2 across the call */ \
2656 _argvec[1] = (unsigned long)_orig.r2; \
2657 _argvec[2] = (unsigned long)_orig.nraddr; \
2658 _argvec[2+1] = (unsigned long)arg1; \
2659 _argvec[2+2] = (unsigned long)arg2; \
2660 _argvec[2+3] = (unsigned long)arg3; \
2661 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002662 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002663 "mr 11,%1\n\t" \
2664 "std 2,-16(11)\n\t" /* save tocptr */ \
2665 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2666 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2667 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2668 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2669 "ld 11, 0(11)\n\t" /* target->r11 */ \
2670 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2671 "mr 11,%1\n\t" \
2672 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002673 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2674 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002675 : /*out*/ "=r" (_res) \
2676 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002677 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002678 ); \
2679 lval = (__typeof__(lval)) _res; \
2680 } while (0)
2681
2682#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2683 do { \
2684 volatile OrigFn _orig = (orig); \
2685 volatile unsigned long _argvec[3+4]; \
2686 volatile unsigned long _res; \
2687 /* _argvec[0] holds current r2 across the call */ \
2688 _argvec[1] = (unsigned long)_orig.r2; \
2689 _argvec[2] = (unsigned long)_orig.nraddr; \
2690 _argvec[2+1] = (unsigned long)arg1; \
2691 _argvec[2+2] = (unsigned long)arg2; \
2692 _argvec[2+3] = (unsigned long)arg3; \
2693 _argvec[2+4] = (unsigned long)arg4; \
2694 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002695 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002696 "mr 11,%1\n\t" \
2697 "std 2,-16(11)\n\t" /* save tocptr */ \
2698 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2699 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2700 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2701 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2702 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2703 "ld 11, 0(11)\n\t" /* target->r11 */ \
2704 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2705 "mr 11,%1\n\t" \
2706 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002707 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2708 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002709 : /*out*/ "=r" (_res) \
2710 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002711 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002712 ); \
2713 lval = (__typeof__(lval)) _res; \
2714 } while (0)
2715
2716#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2717 do { \
2718 volatile OrigFn _orig = (orig); \
2719 volatile unsigned long _argvec[3+5]; \
2720 volatile unsigned long _res; \
2721 /* _argvec[0] holds current r2 across the call */ \
2722 _argvec[1] = (unsigned long)_orig.r2; \
2723 _argvec[2] = (unsigned long)_orig.nraddr; \
2724 _argvec[2+1] = (unsigned long)arg1; \
2725 _argvec[2+2] = (unsigned long)arg2; \
2726 _argvec[2+3] = (unsigned long)arg3; \
2727 _argvec[2+4] = (unsigned long)arg4; \
2728 _argvec[2+5] = (unsigned long)arg5; \
2729 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002730 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002731 "mr 11,%1\n\t" \
2732 "std 2,-16(11)\n\t" /* save tocptr */ \
2733 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2734 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2735 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2736 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2737 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2738 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2739 "ld 11, 0(11)\n\t" /* target->r11 */ \
2740 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2741 "mr 11,%1\n\t" \
2742 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002743 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2744 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002745 : /*out*/ "=r" (_res) \
2746 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002747 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002748 ); \
2749 lval = (__typeof__(lval)) _res; \
2750 } while (0)
2751
2752#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2753 do { \
2754 volatile OrigFn _orig = (orig); \
2755 volatile unsigned long _argvec[3+6]; \
2756 volatile unsigned long _res; \
2757 /* _argvec[0] holds current r2 across the call */ \
2758 _argvec[1] = (unsigned long)_orig.r2; \
2759 _argvec[2] = (unsigned long)_orig.nraddr; \
2760 _argvec[2+1] = (unsigned long)arg1; \
2761 _argvec[2+2] = (unsigned long)arg2; \
2762 _argvec[2+3] = (unsigned long)arg3; \
2763 _argvec[2+4] = (unsigned long)arg4; \
2764 _argvec[2+5] = (unsigned long)arg5; \
2765 _argvec[2+6] = (unsigned long)arg6; \
2766 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002767 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002768 "mr 11,%1\n\t" \
2769 "std 2,-16(11)\n\t" /* save tocptr */ \
2770 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2771 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2772 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2773 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2774 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2775 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2776 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2777 "ld 11, 0(11)\n\t" /* target->r11 */ \
2778 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2779 "mr 11,%1\n\t" \
2780 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002781 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2782 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002783 : /*out*/ "=r" (_res) \
2784 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002785 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002786 ); \
2787 lval = (__typeof__(lval)) _res; \
2788 } while (0)
2789
2790#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2791 arg7) \
2792 do { \
2793 volatile OrigFn _orig = (orig); \
2794 volatile unsigned long _argvec[3+7]; \
2795 volatile unsigned long _res; \
2796 /* _argvec[0] holds current r2 across the call */ \
2797 _argvec[1] = (unsigned long)_orig.r2; \
2798 _argvec[2] = (unsigned long)_orig.nraddr; \
2799 _argvec[2+1] = (unsigned long)arg1; \
2800 _argvec[2+2] = (unsigned long)arg2; \
2801 _argvec[2+3] = (unsigned long)arg3; \
2802 _argvec[2+4] = (unsigned long)arg4; \
2803 _argvec[2+5] = (unsigned long)arg5; \
2804 _argvec[2+6] = (unsigned long)arg6; \
2805 _argvec[2+7] = (unsigned long)arg7; \
2806 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002807 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002808 "mr 11,%1\n\t" \
2809 "std 2,-16(11)\n\t" /* save tocptr */ \
2810 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2811 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2812 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2813 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2814 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2815 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2816 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2817 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2818 "ld 11, 0(11)\n\t" /* target->r11 */ \
2819 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2820 "mr 11,%1\n\t" \
2821 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002822 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2823 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002824 : /*out*/ "=r" (_res) \
2825 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002826 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002827 ); \
2828 lval = (__typeof__(lval)) _res; \
2829 } while (0)
2830
2831#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2832 arg7,arg8) \
2833 do { \
2834 volatile OrigFn _orig = (orig); \
2835 volatile unsigned long _argvec[3+8]; \
2836 volatile unsigned long _res; \
2837 /* _argvec[0] holds current r2 across the call */ \
2838 _argvec[1] = (unsigned long)_orig.r2; \
2839 _argvec[2] = (unsigned long)_orig.nraddr; \
2840 _argvec[2+1] = (unsigned long)arg1; \
2841 _argvec[2+2] = (unsigned long)arg2; \
2842 _argvec[2+3] = (unsigned long)arg3; \
2843 _argvec[2+4] = (unsigned long)arg4; \
2844 _argvec[2+5] = (unsigned long)arg5; \
2845 _argvec[2+6] = (unsigned long)arg6; \
2846 _argvec[2+7] = (unsigned long)arg7; \
2847 _argvec[2+8] = (unsigned long)arg8; \
2848 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002849 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002850 "mr 11,%1\n\t" \
2851 "std 2,-16(11)\n\t" /* save tocptr */ \
2852 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2853 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2854 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2855 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2856 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2857 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2858 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2859 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2860 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2861 "ld 11, 0(11)\n\t" /* target->r11 */ \
2862 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2863 "mr 11,%1\n\t" \
2864 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002865 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2866 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002867 : /*out*/ "=r" (_res) \
2868 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002869 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002870 ); \
2871 lval = (__typeof__(lval)) _res; \
2872 } while (0)
2873
2874#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2875 arg7,arg8,arg9) \
2876 do { \
2877 volatile OrigFn _orig = (orig); \
2878 volatile unsigned long _argvec[3+9]; \
2879 volatile unsigned long _res; \
2880 /* _argvec[0] holds current r2 across the call */ \
2881 _argvec[1] = (unsigned long)_orig.r2; \
2882 _argvec[2] = (unsigned long)_orig.nraddr; \
2883 _argvec[2+1] = (unsigned long)arg1; \
2884 _argvec[2+2] = (unsigned long)arg2; \
2885 _argvec[2+3] = (unsigned long)arg3; \
2886 _argvec[2+4] = (unsigned long)arg4; \
2887 _argvec[2+5] = (unsigned long)arg5; \
2888 _argvec[2+6] = (unsigned long)arg6; \
2889 _argvec[2+7] = (unsigned long)arg7; \
2890 _argvec[2+8] = (unsigned long)arg8; \
2891 _argvec[2+9] = (unsigned long)arg9; \
2892 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002893 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002894 "mr 11,%1\n\t" \
2895 "std 2,-16(11)\n\t" /* save tocptr */ \
2896 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2897 "addi 1,1,-128\n\t" /* expand stack frame */ \
2898 /* arg9 */ \
2899 "ld 3,72(11)\n\t" \
2900 "std 3,112(1)\n\t" \
2901 /* args1-8 */ \
2902 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2903 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2904 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2905 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2906 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2907 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2908 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2909 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2910 "ld 11, 0(11)\n\t" /* target->r11 */ \
2911 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2912 "mr 11,%1\n\t" \
2913 "mr %0,3\n\t" \
2914 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00002915 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002916 : /*out*/ "=r" (_res) \
2917 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002918 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002919 ); \
2920 lval = (__typeof__(lval)) _res; \
2921 } while (0)
2922
2923#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2924 arg7,arg8,arg9,arg10) \
2925 do { \
2926 volatile OrigFn _orig = (orig); \
2927 volatile unsigned long _argvec[3+10]; \
2928 volatile unsigned long _res; \
2929 /* _argvec[0] holds current r2 across the call */ \
2930 _argvec[1] = (unsigned long)_orig.r2; \
2931 _argvec[2] = (unsigned long)_orig.nraddr; \
2932 _argvec[2+1] = (unsigned long)arg1; \
2933 _argvec[2+2] = (unsigned long)arg2; \
2934 _argvec[2+3] = (unsigned long)arg3; \
2935 _argvec[2+4] = (unsigned long)arg4; \
2936 _argvec[2+5] = (unsigned long)arg5; \
2937 _argvec[2+6] = (unsigned long)arg6; \
2938 _argvec[2+7] = (unsigned long)arg7; \
2939 _argvec[2+8] = (unsigned long)arg8; \
2940 _argvec[2+9] = (unsigned long)arg9; \
2941 _argvec[2+10] = (unsigned long)arg10; \
2942 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002943 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002944 "mr 11,%1\n\t" \
2945 "std 2,-16(11)\n\t" /* save tocptr */ \
2946 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2947 "addi 1,1,-128\n\t" /* expand stack frame */ \
2948 /* arg10 */ \
2949 "ld 3,80(11)\n\t" \
2950 "std 3,120(1)\n\t" \
2951 /* arg9 */ \
2952 "ld 3,72(11)\n\t" \
2953 "std 3,112(1)\n\t" \
2954 /* args1-8 */ \
2955 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2956 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2957 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2958 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2959 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2960 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2961 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2962 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2963 "ld 11, 0(11)\n\t" /* target->r11 */ \
2964 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2965 "mr 11,%1\n\t" \
2966 "mr %0,3\n\t" \
2967 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00002968 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002969 : /*out*/ "=r" (_res) \
2970 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002971 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002972 ); \
2973 lval = (__typeof__(lval)) _res; \
2974 } while (0)
2975
2976#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2977 arg7,arg8,arg9,arg10,arg11) \
2978 do { \
2979 volatile OrigFn _orig = (orig); \
2980 volatile unsigned long _argvec[3+11]; \
2981 volatile unsigned long _res; \
2982 /* _argvec[0] holds current r2 across the call */ \
2983 _argvec[1] = (unsigned long)_orig.r2; \
2984 _argvec[2] = (unsigned long)_orig.nraddr; \
2985 _argvec[2+1] = (unsigned long)arg1; \
2986 _argvec[2+2] = (unsigned long)arg2; \
2987 _argvec[2+3] = (unsigned long)arg3; \
2988 _argvec[2+4] = (unsigned long)arg4; \
2989 _argvec[2+5] = (unsigned long)arg5; \
2990 _argvec[2+6] = (unsigned long)arg6; \
2991 _argvec[2+7] = (unsigned long)arg7; \
2992 _argvec[2+8] = (unsigned long)arg8; \
2993 _argvec[2+9] = (unsigned long)arg9; \
2994 _argvec[2+10] = (unsigned long)arg10; \
2995 _argvec[2+11] = (unsigned long)arg11; \
2996 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002997 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002998 "mr 11,%1\n\t" \
2999 "std 2,-16(11)\n\t" /* save tocptr */ \
3000 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3001 "addi 1,1,-144\n\t" /* expand stack frame */ \
3002 /* arg11 */ \
3003 "ld 3,88(11)\n\t" \
3004 "std 3,128(1)\n\t" \
3005 /* arg10 */ \
3006 "ld 3,80(11)\n\t" \
3007 "std 3,120(1)\n\t" \
3008 /* arg9 */ \
3009 "ld 3,72(11)\n\t" \
3010 "std 3,112(1)\n\t" \
3011 /* args1-8 */ \
3012 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3013 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3014 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3015 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3016 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3017 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3018 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3019 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3020 "ld 11, 0(11)\n\t" /* target->r11 */ \
3021 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3022 "mr 11,%1\n\t" \
3023 "mr %0,3\n\t" \
3024 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00003025 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00003026 : /*out*/ "=r" (_res) \
3027 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00003028 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00003029 ); \
3030 lval = (__typeof__(lval)) _res; \
3031 } while (0)
3032
3033#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3034 arg7,arg8,arg9,arg10,arg11,arg12) \
3035 do { \
3036 volatile OrigFn _orig = (orig); \
3037 volatile unsigned long _argvec[3+12]; \
3038 volatile unsigned long _res; \
3039 /* _argvec[0] holds current r2 across the call */ \
3040 _argvec[1] = (unsigned long)_orig.r2; \
3041 _argvec[2] = (unsigned long)_orig.nraddr; \
3042 _argvec[2+1] = (unsigned long)arg1; \
3043 _argvec[2+2] = (unsigned long)arg2; \
3044 _argvec[2+3] = (unsigned long)arg3; \
3045 _argvec[2+4] = (unsigned long)arg4; \
3046 _argvec[2+5] = (unsigned long)arg5; \
3047 _argvec[2+6] = (unsigned long)arg6; \
3048 _argvec[2+7] = (unsigned long)arg7; \
3049 _argvec[2+8] = (unsigned long)arg8; \
3050 _argvec[2+9] = (unsigned long)arg9; \
3051 _argvec[2+10] = (unsigned long)arg10; \
3052 _argvec[2+11] = (unsigned long)arg11; \
3053 _argvec[2+12] = (unsigned long)arg12; \
3054 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003055 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00003056 "mr 11,%1\n\t" \
3057 "std 2,-16(11)\n\t" /* save tocptr */ \
3058 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3059 "addi 1,1,-144\n\t" /* expand stack frame */ \
3060 /* arg12 */ \
3061 "ld 3,96(11)\n\t" \
3062 "std 3,136(1)\n\t" \
3063 /* arg11 */ \
3064 "ld 3,88(11)\n\t" \
3065 "std 3,128(1)\n\t" \
3066 /* arg10 */ \
3067 "ld 3,80(11)\n\t" \
3068 "std 3,120(1)\n\t" \
3069 /* arg9 */ \
3070 "ld 3,72(11)\n\t" \
3071 "std 3,112(1)\n\t" \
3072 /* args1-8 */ \
3073 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3074 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3075 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3076 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3077 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3078 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3079 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3080 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3081 "ld 11, 0(11)\n\t" /* target->r11 */ \
3082 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3083 "mr 11,%1\n\t" \
3084 "mr %0,3\n\t" \
3085 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00003086 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00003087 : /*out*/ "=r" (_res) \
3088 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00003089 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00003090 ); \
3091 lval = (__typeof__(lval)) _res; \
3092 } while (0)
3093
carllcae0cc22014-08-07 23:17:29 +00003094#endif /* PLAT_ppc64be_linux */
sewardjf5c1a7f2006-10-17 01:32:48 +00003095
sewardj59570ff2010-01-01 11:59:33 +00003096/* ------------------------- arm-linux ------------------------- */
3097
3098#if defined(PLAT_arm_linux)
3099
3100/* These regs are trashed by the hidden call. */
3101#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
3102
tom4118e0f2012-08-02 09:23:45 +00003103/* Macros to save and align the stack before making a function
3104 call and restore it afterwards as gcc may not keep the stack
3105 pointer aligned if it doesn't realise calls are being made
3106 to other functions. */
3107
sewardj567e5bb2012-08-04 19:23:54 +00003108/* This is a bit tricky. We store the original stack pointer in r10
3109 as it is callee-saves. gcc doesn't allow the use of r11 for some
3110 reason. Also, we can't directly "bic" the stack pointer in thumb
3111 mode since r13 isn't an allowed register number in that context.
3112 So use r4 as a temporary, since that is about to get trashed
3113 anyway, just after each use of this macro. Side effect is we need
3114 to be very careful about any future changes, since
3115 VALGRIND_ALIGN_STACK simply assumes r4 is usable. */
tom4118e0f2012-08-02 09:23:45 +00003116#define VALGRIND_ALIGN_STACK \
sewardj567e5bb2012-08-04 19:23:54 +00003117 "mov r10, sp\n\t" \
3118 "mov r4, sp\n\t" \
3119 "bic r4, r4, #7\n\t" \
3120 "mov sp, r4\n\t"
tom4118e0f2012-08-02 09:23:45 +00003121#define VALGRIND_RESTORE_STACK \
sewardj567e5bb2012-08-04 19:23:54 +00003122 "mov sp, r10\n\t"
tom4118e0f2012-08-02 09:23:45 +00003123
sewardj59570ff2010-01-01 11:59:33 +00003124/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
3125 long) == 4. */
3126
3127#define CALL_FN_W_v(lval, orig) \
3128 do { \
3129 volatile OrigFn _orig = (orig); \
3130 volatile unsigned long _argvec[1]; \
3131 volatile unsigned long _res; \
3132 _argvec[0] = (unsigned long)_orig.nraddr; \
3133 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003134 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003135 "ldr r4, [%1] \n\t" /* target->r4 */ \
3136 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003137 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003138 "mov %0, r0\n" \
3139 : /*out*/ "=r" (_res) \
3140 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003141 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003142 ); \
3143 lval = (__typeof__(lval)) _res; \
3144 } while (0)
3145
3146#define CALL_FN_W_W(lval, orig, arg1) \
3147 do { \
3148 volatile OrigFn _orig = (orig); \
3149 volatile unsigned long _argvec[2]; \
3150 volatile unsigned long _res; \
3151 _argvec[0] = (unsigned long)_orig.nraddr; \
3152 _argvec[1] = (unsigned long)(arg1); \
3153 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003154 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003155 "ldr r0, [%1, #4] \n\t" \
3156 "ldr r4, [%1] \n\t" /* target->r4 */ \
3157 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003158 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003159 "mov %0, r0\n" \
3160 : /*out*/ "=r" (_res) \
3161 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003162 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003163 ); \
3164 lval = (__typeof__(lval)) _res; \
3165 } while (0)
3166
3167#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3168 do { \
3169 volatile OrigFn _orig = (orig); \
3170 volatile unsigned long _argvec[3]; \
3171 volatile unsigned long _res; \
3172 _argvec[0] = (unsigned long)_orig.nraddr; \
3173 _argvec[1] = (unsigned long)(arg1); \
3174 _argvec[2] = (unsigned long)(arg2); \
3175 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003176 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003177 "ldr r0, [%1, #4] \n\t" \
3178 "ldr r1, [%1, #8] \n\t" \
3179 "ldr r4, [%1] \n\t" /* target->r4 */ \
3180 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003181 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003182 "mov %0, r0\n" \
3183 : /*out*/ "=r" (_res) \
3184 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003185 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003186 ); \
3187 lval = (__typeof__(lval)) _res; \
3188 } while (0)
3189
3190#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3191 do { \
3192 volatile OrigFn _orig = (orig); \
3193 volatile unsigned long _argvec[4]; \
3194 volatile unsigned long _res; \
3195 _argvec[0] = (unsigned long)_orig.nraddr; \
3196 _argvec[1] = (unsigned long)(arg1); \
3197 _argvec[2] = (unsigned long)(arg2); \
3198 _argvec[3] = (unsigned long)(arg3); \
3199 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003200 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003201 "ldr r0, [%1, #4] \n\t" \
3202 "ldr r1, [%1, #8] \n\t" \
3203 "ldr r2, [%1, #12] \n\t" \
3204 "ldr r4, [%1] \n\t" /* target->r4 */ \
3205 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003206 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003207 "mov %0, r0\n" \
3208 : /*out*/ "=r" (_res) \
3209 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003210 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003211 ); \
3212 lval = (__typeof__(lval)) _res; \
3213 } while (0)
3214
3215#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3216 do { \
3217 volatile OrigFn _orig = (orig); \
3218 volatile unsigned long _argvec[5]; \
3219 volatile unsigned long _res; \
3220 _argvec[0] = (unsigned long)_orig.nraddr; \
3221 _argvec[1] = (unsigned long)(arg1); \
3222 _argvec[2] = (unsigned long)(arg2); \
3223 _argvec[3] = (unsigned long)(arg3); \
3224 _argvec[4] = (unsigned long)(arg4); \
3225 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003226 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003227 "ldr r0, [%1, #4] \n\t" \
3228 "ldr r1, [%1, #8] \n\t" \
3229 "ldr r2, [%1, #12] \n\t" \
3230 "ldr r3, [%1, #16] \n\t" \
3231 "ldr r4, [%1] \n\t" /* target->r4 */ \
3232 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003233 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003234 "mov %0, r0" \
3235 : /*out*/ "=r" (_res) \
3236 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003237 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003238 ); \
3239 lval = (__typeof__(lval)) _res; \
3240 } while (0)
3241
3242#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3243 do { \
3244 volatile OrigFn _orig = (orig); \
3245 volatile unsigned long _argvec[6]; \
3246 volatile unsigned long _res; \
3247 _argvec[0] = (unsigned long)_orig.nraddr; \
3248 _argvec[1] = (unsigned long)(arg1); \
3249 _argvec[2] = (unsigned long)(arg2); \
3250 _argvec[3] = (unsigned long)(arg3); \
3251 _argvec[4] = (unsigned long)(arg4); \
3252 _argvec[5] = (unsigned long)(arg5); \
3253 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003254 VALGRIND_ALIGN_STACK \
3255 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003256 "ldr r0, [%1, #20] \n\t" \
3257 "push {r0} \n\t" \
3258 "ldr r0, [%1, #4] \n\t" \
3259 "ldr r1, [%1, #8] \n\t" \
3260 "ldr r2, [%1, #12] \n\t" \
3261 "ldr r3, [%1, #16] \n\t" \
3262 "ldr r4, [%1] \n\t" /* target->r4 */ \
3263 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003264 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003265 "mov %0, r0" \
3266 : /*out*/ "=r" (_res) \
3267 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003268 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003269 ); \
3270 lval = (__typeof__(lval)) _res; \
3271 } while (0)
3272
3273#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3274 do { \
3275 volatile OrigFn _orig = (orig); \
3276 volatile unsigned long _argvec[7]; \
3277 volatile unsigned long _res; \
3278 _argvec[0] = (unsigned long)_orig.nraddr; \
3279 _argvec[1] = (unsigned long)(arg1); \
3280 _argvec[2] = (unsigned long)(arg2); \
3281 _argvec[3] = (unsigned long)(arg3); \
3282 _argvec[4] = (unsigned long)(arg4); \
3283 _argvec[5] = (unsigned long)(arg5); \
3284 _argvec[6] = (unsigned long)(arg6); \
3285 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003286 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003287 "ldr r0, [%1, #20] \n\t" \
3288 "ldr r1, [%1, #24] \n\t" \
3289 "push {r0, r1} \n\t" \
3290 "ldr r0, [%1, #4] \n\t" \
3291 "ldr r1, [%1, #8] \n\t" \
3292 "ldr r2, [%1, #12] \n\t" \
3293 "ldr r3, [%1, #16] \n\t" \
3294 "ldr r4, [%1] \n\t" /* target->r4 */ \
3295 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003296 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003297 "mov %0, r0" \
3298 : /*out*/ "=r" (_res) \
3299 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003300 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003301 ); \
3302 lval = (__typeof__(lval)) _res; \
3303 } while (0)
3304
3305#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3306 arg7) \
3307 do { \
3308 volatile OrigFn _orig = (orig); \
3309 volatile unsigned long _argvec[8]; \
3310 volatile unsigned long _res; \
3311 _argvec[0] = (unsigned long)_orig.nraddr; \
3312 _argvec[1] = (unsigned long)(arg1); \
3313 _argvec[2] = (unsigned long)(arg2); \
3314 _argvec[3] = (unsigned long)(arg3); \
3315 _argvec[4] = (unsigned long)(arg4); \
3316 _argvec[5] = (unsigned long)(arg5); \
3317 _argvec[6] = (unsigned long)(arg6); \
3318 _argvec[7] = (unsigned long)(arg7); \
3319 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003320 VALGRIND_ALIGN_STACK \
3321 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003322 "ldr r0, [%1, #20] \n\t" \
3323 "ldr r1, [%1, #24] \n\t" \
3324 "ldr r2, [%1, #28] \n\t" \
3325 "push {r0, r1, r2} \n\t" \
3326 "ldr r0, [%1, #4] \n\t" \
3327 "ldr r1, [%1, #8] \n\t" \
3328 "ldr r2, [%1, #12] \n\t" \
3329 "ldr r3, [%1, #16] \n\t" \
3330 "ldr r4, [%1] \n\t" /* target->r4 */ \
3331 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003332 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003333 "mov %0, r0" \
3334 : /*out*/ "=r" (_res) \
3335 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003336 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003337 ); \
3338 lval = (__typeof__(lval)) _res; \
3339 } while (0)
3340
3341#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3342 arg7,arg8) \
3343 do { \
3344 volatile OrigFn _orig = (orig); \
3345 volatile unsigned long _argvec[9]; \
3346 volatile unsigned long _res; \
3347 _argvec[0] = (unsigned long)_orig.nraddr; \
3348 _argvec[1] = (unsigned long)(arg1); \
3349 _argvec[2] = (unsigned long)(arg2); \
3350 _argvec[3] = (unsigned long)(arg3); \
3351 _argvec[4] = (unsigned long)(arg4); \
3352 _argvec[5] = (unsigned long)(arg5); \
3353 _argvec[6] = (unsigned long)(arg6); \
3354 _argvec[7] = (unsigned long)(arg7); \
3355 _argvec[8] = (unsigned long)(arg8); \
3356 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003357 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003358 "ldr r0, [%1, #20] \n\t" \
3359 "ldr r1, [%1, #24] \n\t" \
3360 "ldr r2, [%1, #28] \n\t" \
3361 "ldr r3, [%1, #32] \n\t" \
3362 "push {r0, r1, r2, r3} \n\t" \
3363 "ldr r0, [%1, #4] \n\t" \
3364 "ldr r1, [%1, #8] \n\t" \
3365 "ldr r2, [%1, #12] \n\t" \
3366 "ldr r3, [%1, #16] \n\t" \
3367 "ldr r4, [%1] \n\t" /* target->r4 */ \
3368 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003369 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003370 "mov %0, r0" \
3371 : /*out*/ "=r" (_res) \
3372 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003373 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003374 ); \
3375 lval = (__typeof__(lval)) _res; \
3376 } while (0)
3377
3378#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3379 arg7,arg8,arg9) \
3380 do { \
3381 volatile OrigFn _orig = (orig); \
3382 volatile unsigned long _argvec[10]; \
3383 volatile unsigned long _res; \
3384 _argvec[0] = (unsigned long)_orig.nraddr; \
3385 _argvec[1] = (unsigned long)(arg1); \
3386 _argvec[2] = (unsigned long)(arg2); \
3387 _argvec[3] = (unsigned long)(arg3); \
3388 _argvec[4] = (unsigned long)(arg4); \
3389 _argvec[5] = (unsigned long)(arg5); \
3390 _argvec[6] = (unsigned long)(arg6); \
3391 _argvec[7] = (unsigned long)(arg7); \
3392 _argvec[8] = (unsigned long)(arg8); \
3393 _argvec[9] = (unsigned long)(arg9); \
3394 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003395 VALGRIND_ALIGN_STACK \
3396 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003397 "ldr r0, [%1, #20] \n\t" \
3398 "ldr r1, [%1, #24] \n\t" \
3399 "ldr r2, [%1, #28] \n\t" \
3400 "ldr r3, [%1, #32] \n\t" \
3401 "ldr r4, [%1, #36] \n\t" \
3402 "push {r0, r1, r2, r3, r4} \n\t" \
3403 "ldr r0, [%1, #4] \n\t" \
3404 "ldr r1, [%1, #8] \n\t" \
3405 "ldr r2, [%1, #12] \n\t" \
3406 "ldr r3, [%1, #16] \n\t" \
3407 "ldr r4, [%1] \n\t" /* target->r4 */ \
3408 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003409 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003410 "mov %0, r0" \
3411 : /*out*/ "=r" (_res) \
3412 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003413 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003414 ); \
3415 lval = (__typeof__(lval)) _res; \
3416 } while (0)
3417
3418#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3419 arg7,arg8,arg9,arg10) \
3420 do { \
3421 volatile OrigFn _orig = (orig); \
3422 volatile unsigned long _argvec[11]; \
3423 volatile unsigned long _res; \
3424 _argvec[0] = (unsigned long)_orig.nraddr; \
3425 _argvec[1] = (unsigned long)(arg1); \
3426 _argvec[2] = (unsigned long)(arg2); \
3427 _argvec[3] = (unsigned long)(arg3); \
3428 _argvec[4] = (unsigned long)(arg4); \
3429 _argvec[5] = (unsigned long)(arg5); \
3430 _argvec[6] = (unsigned long)(arg6); \
3431 _argvec[7] = (unsigned long)(arg7); \
3432 _argvec[8] = (unsigned long)(arg8); \
3433 _argvec[9] = (unsigned long)(arg9); \
3434 _argvec[10] = (unsigned long)(arg10); \
3435 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003436 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003437 "ldr r0, [%1, #40] \n\t" \
3438 "push {r0} \n\t" \
3439 "ldr r0, [%1, #20] \n\t" \
3440 "ldr r1, [%1, #24] \n\t" \
3441 "ldr r2, [%1, #28] \n\t" \
3442 "ldr r3, [%1, #32] \n\t" \
3443 "ldr r4, [%1, #36] \n\t" \
3444 "push {r0, r1, r2, r3, r4} \n\t" \
3445 "ldr r0, [%1, #4] \n\t" \
3446 "ldr r1, [%1, #8] \n\t" \
3447 "ldr r2, [%1, #12] \n\t" \
3448 "ldr r3, [%1, #16] \n\t" \
3449 "ldr r4, [%1] \n\t" /* target->r4 */ \
3450 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003451 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003452 "mov %0, r0" \
3453 : /*out*/ "=r" (_res) \
3454 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003455 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003456 ); \
3457 lval = (__typeof__(lval)) _res; \
3458 } while (0)
3459
3460#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3461 arg6,arg7,arg8,arg9,arg10, \
3462 arg11) \
3463 do { \
3464 volatile OrigFn _orig = (orig); \
3465 volatile unsigned long _argvec[12]; \
3466 volatile unsigned long _res; \
3467 _argvec[0] = (unsigned long)_orig.nraddr; \
3468 _argvec[1] = (unsigned long)(arg1); \
3469 _argvec[2] = (unsigned long)(arg2); \
3470 _argvec[3] = (unsigned long)(arg3); \
3471 _argvec[4] = (unsigned long)(arg4); \
3472 _argvec[5] = (unsigned long)(arg5); \
3473 _argvec[6] = (unsigned long)(arg6); \
3474 _argvec[7] = (unsigned long)(arg7); \
3475 _argvec[8] = (unsigned long)(arg8); \
3476 _argvec[9] = (unsigned long)(arg9); \
3477 _argvec[10] = (unsigned long)(arg10); \
3478 _argvec[11] = (unsigned long)(arg11); \
3479 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003480 VALGRIND_ALIGN_STACK \
3481 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003482 "ldr r0, [%1, #40] \n\t" \
3483 "ldr r1, [%1, #44] \n\t" \
3484 "push {r0, r1} \n\t" \
3485 "ldr r0, [%1, #20] \n\t" \
3486 "ldr r1, [%1, #24] \n\t" \
3487 "ldr r2, [%1, #28] \n\t" \
3488 "ldr r3, [%1, #32] \n\t" \
3489 "ldr r4, [%1, #36] \n\t" \
3490 "push {r0, r1, r2, r3, r4} \n\t" \
3491 "ldr r0, [%1, #4] \n\t" \
3492 "ldr r1, [%1, #8] \n\t" \
3493 "ldr r2, [%1, #12] \n\t" \
3494 "ldr r3, [%1, #16] \n\t" \
3495 "ldr r4, [%1] \n\t" /* target->r4 */ \
3496 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003497 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003498 "mov %0, r0" \
3499 : /*out*/ "=r" (_res) \
3500 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003501 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003502 ); \
3503 lval = (__typeof__(lval)) _res; \
3504 } while (0)
3505
3506#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3507 arg6,arg7,arg8,arg9,arg10, \
3508 arg11,arg12) \
3509 do { \
3510 volatile OrigFn _orig = (orig); \
3511 volatile unsigned long _argvec[13]; \
3512 volatile unsigned long _res; \
3513 _argvec[0] = (unsigned long)_orig.nraddr; \
3514 _argvec[1] = (unsigned long)(arg1); \
3515 _argvec[2] = (unsigned long)(arg2); \
3516 _argvec[3] = (unsigned long)(arg3); \
3517 _argvec[4] = (unsigned long)(arg4); \
3518 _argvec[5] = (unsigned long)(arg5); \
3519 _argvec[6] = (unsigned long)(arg6); \
3520 _argvec[7] = (unsigned long)(arg7); \
3521 _argvec[8] = (unsigned long)(arg8); \
3522 _argvec[9] = (unsigned long)(arg9); \
3523 _argvec[10] = (unsigned long)(arg10); \
3524 _argvec[11] = (unsigned long)(arg11); \
3525 _argvec[12] = (unsigned long)(arg12); \
3526 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003527 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003528 "ldr r0, [%1, #40] \n\t" \
3529 "ldr r1, [%1, #44] \n\t" \
3530 "ldr r2, [%1, #48] \n\t" \
3531 "push {r0, r1, r2} \n\t" \
3532 "ldr r0, [%1, #20] \n\t" \
3533 "ldr r1, [%1, #24] \n\t" \
3534 "ldr r2, [%1, #28] \n\t" \
3535 "ldr r3, [%1, #32] \n\t" \
3536 "ldr r4, [%1, #36] \n\t" \
3537 "push {r0, r1, r2, r3, r4} \n\t" \
3538 "ldr r0, [%1, #4] \n\t" \
3539 "ldr r1, [%1, #8] \n\t" \
3540 "ldr r2, [%1, #12] \n\t" \
3541 "ldr r3, [%1, #16] \n\t" \
3542 "ldr r4, [%1] \n\t" /* target->r4 */ \
3543 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003544 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003545 "mov %0, r0" \
3546 : /*out*/ "=r" (_res) \
3547 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003548 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003549 ); \
3550 lval = (__typeof__(lval)) _res; \
3551 } while (0)
3552
3553#endif /* PLAT_arm_linux */
3554
sewardjf0c12502014-01-12 12:54:00 +00003555/* ------------------------ arm64-linux ------------------------ */
3556
3557#if defined(PLAT_arm64_linux)
3558
3559/* These regs are trashed by the hidden call. */
3560#define __CALLER_SAVED_REGS \
3561 "x0", "x1", "x2", "x3","x4", "x5", "x6", "x7", "x8", "x9", \
3562 "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", \
sewardjbb9b1b92014-03-09 09:46:04 +00003563 "x18", "x19", "x20", "x30", \
sewardjf0c12502014-01-12 12:54:00 +00003564 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \
3565 "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", \
3566 "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", \
3567 "v26", "v27", "v28", "v29", "v30", "v31"
3568
sewardjbb9b1b92014-03-09 09:46:04 +00003569/* x21 is callee-saved, so we can use it to save and restore SP around
3570 the hidden call. */
3571#define VALGRIND_ALIGN_STACK \
3572 "mov x21, sp\n\t" \
3573 "bic sp, x21, #15\n\t"
3574#define VALGRIND_RESTORE_STACK \
3575 "mov sp, x21\n\t"
sewardjf0c12502014-01-12 12:54:00 +00003576
3577/* These CALL_FN_ macros assume that on arm64-linux,
3578 sizeof(unsigned long) == 8. */
3579
3580#define CALL_FN_W_v(lval, orig) \
3581 do { \
3582 volatile OrigFn _orig = (orig); \
3583 volatile unsigned long _argvec[1]; \
3584 volatile unsigned long _res; \
3585 _argvec[0] = (unsigned long)_orig.nraddr; \
3586 __asm__ volatile( \
3587 VALGRIND_ALIGN_STACK \
3588 "ldr x8, [%1] \n\t" /* target->x8 */ \
3589 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3590 VALGRIND_RESTORE_STACK \
3591 "mov %0, x0\n" \
3592 : /*out*/ "=r" (_res) \
3593 : /*in*/ "0" (&_argvec[0]) \
sewardjbb9b1b92014-03-09 09:46:04 +00003594 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00003595 ); \
3596 lval = (__typeof__(lval)) _res; \
3597 } while (0)
3598
3599#define CALL_FN_W_W(lval, orig, arg1) \
3600 do { \
3601 volatile OrigFn _orig = (orig); \
3602 volatile unsigned long _argvec[2]; \
3603 volatile unsigned long _res; \
3604 _argvec[0] = (unsigned long)_orig.nraddr; \
3605 _argvec[1] = (unsigned long)(arg1); \
3606 __asm__ volatile( \
3607 VALGRIND_ALIGN_STACK \
3608 "ldr x0, [%1, #8] \n\t" \
3609 "ldr x8, [%1] \n\t" /* target->x8 */ \
3610 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3611 VALGRIND_RESTORE_STACK \
3612 "mov %0, x0\n" \
3613 : /*out*/ "=r" (_res) \
3614 : /*in*/ "0" (&_argvec[0]) \
sewardjbb9b1b92014-03-09 09:46:04 +00003615 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00003616 ); \
3617 lval = (__typeof__(lval)) _res; \
3618 } while (0)
3619
3620#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3621 do { \
3622 volatile OrigFn _orig = (orig); \
3623 volatile unsigned long _argvec[3]; \
3624 volatile unsigned long _res; \
3625 _argvec[0] = (unsigned long)_orig.nraddr; \
3626 _argvec[1] = (unsigned long)(arg1); \
3627 _argvec[2] = (unsigned long)(arg2); \
3628 __asm__ volatile( \
3629 VALGRIND_ALIGN_STACK \
3630 "ldr x0, [%1, #8] \n\t" \
3631 "ldr x1, [%1, #16] \n\t" \
3632 "ldr x8, [%1] \n\t" /* target->x8 */ \
3633 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3634 VALGRIND_RESTORE_STACK \
3635 "mov %0, x0\n" \
3636 : /*out*/ "=r" (_res) \
3637 : /*in*/ "0" (&_argvec[0]) \
sewardj91e14602014-03-16 14:21:41 +00003638 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00003639 ); \
3640 lval = (__typeof__(lval)) _res; \
3641 } while (0)
3642
3643#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3644 do { \
3645 volatile OrigFn _orig = (orig); \
3646 volatile unsigned long _argvec[4]; \
3647 volatile unsigned long _res; \
3648 _argvec[0] = (unsigned long)_orig.nraddr; \
3649 _argvec[1] = (unsigned long)(arg1); \
3650 _argvec[2] = (unsigned long)(arg2); \
3651 _argvec[3] = (unsigned long)(arg3); \
3652 __asm__ volatile( \
3653 VALGRIND_ALIGN_STACK \
3654 "ldr x0, [%1, #8] \n\t" \
3655 "ldr x1, [%1, #16] \n\t" \
3656 "ldr x2, [%1, #24] \n\t" \
3657 "ldr x8, [%1] \n\t" /* target->x8 */ \
3658 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3659 VALGRIND_RESTORE_STACK \
3660 "mov %0, x0\n" \
3661 : /*out*/ "=r" (_res) \
3662 : /*in*/ "0" (&_argvec[0]) \
sewardj91e14602014-03-16 14:21:41 +00003663 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00003664 ); \
3665 lval = (__typeof__(lval)) _res; \
3666 } while (0)
3667
3668#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3669 do { \
3670 volatile OrigFn _orig = (orig); \
3671 volatile unsigned long _argvec[5]; \
3672 volatile unsigned long _res; \
3673 _argvec[0] = (unsigned long)_orig.nraddr; \
3674 _argvec[1] = (unsigned long)(arg1); \
3675 _argvec[2] = (unsigned long)(arg2); \
3676 _argvec[3] = (unsigned long)(arg3); \
3677 _argvec[4] = (unsigned long)(arg4); \
3678 __asm__ volatile( \
3679 VALGRIND_ALIGN_STACK \
3680 "ldr x0, [%1, #8] \n\t" \
3681 "ldr x1, [%1, #16] \n\t" \
3682 "ldr x2, [%1, #24] \n\t" \
3683 "ldr x3, [%1, #32] \n\t" \
3684 "ldr x8, [%1] \n\t" /* target->x8 */ \
3685 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3686 VALGRIND_RESTORE_STACK \
3687 "mov %0, x0" \
3688 : /*out*/ "=r" (_res) \
3689 : /*in*/ "0" (&_argvec[0]) \
sewardj91e14602014-03-16 14:21:41 +00003690 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3691 ); \
3692 lval = (__typeof__(lval)) _res; \
3693 } while (0)
3694
3695#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3696 do { \
3697 volatile OrigFn _orig = (orig); \
3698 volatile unsigned long _argvec[6]; \
3699 volatile unsigned long _res; \
3700 _argvec[0] = (unsigned long)_orig.nraddr; \
3701 _argvec[1] = (unsigned long)(arg1); \
3702 _argvec[2] = (unsigned long)(arg2); \
3703 _argvec[3] = (unsigned long)(arg3); \
3704 _argvec[4] = (unsigned long)(arg4); \
3705 _argvec[5] = (unsigned long)(arg5); \
3706 __asm__ volatile( \
3707 VALGRIND_ALIGN_STACK \
3708 "ldr x0, [%1, #8] \n\t" \
3709 "ldr x1, [%1, #16] \n\t" \
3710 "ldr x2, [%1, #24] \n\t" \
3711 "ldr x3, [%1, #32] \n\t" \
3712 "ldr x4, [%1, #40] \n\t" \
3713 "ldr x8, [%1] \n\t" /* target->x8 */ \
3714 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3715 VALGRIND_RESTORE_STACK \
3716 "mov %0, x0" \
3717 : /*out*/ "=r" (_res) \
3718 : /*in*/ "0" (&_argvec[0]) \
3719 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3720 ); \
3721 lval = (__typeof__(lval)) _res; \
3722 } while (0)
3723
3724#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3725 do { \
3726 volatile OrigFn _orig = (orig); \
3727 volatile unsigned long _argvec[7]; \
3728 volatile unsigned long _res; \
3729 _argvec[0] = (unsigned long)_orig.nraddr; \
3730 _argvec[1] = (unsigned long)(arg1); \
3731 _argvec[2] = (unsigned long)(arg2); \
3732 _argvec[3] = (unsigned long)(arg3); \
3733 _argvec[4] = (unsigned long)(arg4); \
3734 _argvec[5] = (unsigned long)(arg5); \
3735 _argvec[6] = (unsigned long)(arg6); \
3736 __asm__ volatile( \
3737 VALGRIND_ALIGN_STACK \
3738 "ldr x0, [%1, #8] \n\t" \
3739 "ldr x1, [%1, #16] \n\t" \
3740 "ldr x2, [%1, #24] \n\t" \
3741 "ldr x3, [%1, #32] \n\t" \
3742 "ldr x4, [%1, #40] \n\t" \
3743 "ldr x5, [%1, #48] \n\t" \
3744 "ldr x8, [%1] \n\t" /* target->x8 */ \
3745 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3746 VALGRIND_RESTORE_STACK \
3747 "mov %0, x0" \
3748 : /*out*/ "=r" (_res) \
3749 : /*in*/ "0" (&_argvec[0]) \
3750 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3751 ); \
3752 lval = (__typeof__(lval)) _res; \
3753 } while (0)
3754
3755#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3756 arg7) \
3757 do { \
3758 volatile OrigFn _orig = (orig); \
3759 volatile unsigned long _argvec[8]; \
3760 volatile unsigned long _res; \
3761 _argvec[0] = (unsigned long)_orig.nraddr; \
3762 _argvec[1] = (unsigned long)(arg1); \
3763 _argvec[2] = (unsigned long)(arg2); \
3764 _argvec[3] = (unsigned long)(arg3); \
3765 _argvec[4] = (unsigned long)(arg4); \
3766 _argvec[5] = (unsigned long)(arg5); \
3767 _argvec[6] = (unsigned long)(arg6); \
3768 _argvec[7] = (unsigned long)(arg7); \
3769 __asm__ volatile( \
3770 VALGRIND_ALIGN_STACK \
3771 "ldr x0, [%1, #8] \n\t" \
3772 "ldr x1, [%1, #16] \n\t" \
3773 "ldr x2, [%1, #24] \n\t" \
3774 "ldr x3, [%1, #32] \n\t" \
3775 "ldr x4, [%1, #40] \n\t" \
3776 "ldr x5, [%1, #48] \n\t" \
3777 "ldr x6, [%1, #56] \n\t" \
3778 "ldr x8, [%1] \n\t" /* target->x8 */ \
3779 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3780 VALGRIND_RESTORE_STACK \
3781 "mov %0, x0" \
3782 : /*out*/ "=r" (_res) \
3783 : /*in*/ "0" (&_argvec[0]) \
3784 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3785 ); \
3786 lval = (__typeof__(lval)) _res; \
3787 } while (0)
3788
3789#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3790 arg7,arg8) \
3791 do { \
3792 volatile OrigFn _orig = (orig); \
3793 volatile unsigned long _argvec[9]; \
3794 volatile unsigned long _res; \
3795 _argvec[0] = (unsigned long)_orig.nraddr; \
3796 _argvec[1] = (unsigned long)(arg1); \
3797 _argvec[2] = (unsigned long)(arg2); \
3798 _argvec[3] = (unsigned long)(arg3); \
3799 _argvec[4] = (unsigned long)(arg4); \
3800 _argvec[5] = (unsigned long)(arg5); \
3801 _argvec[6] = (unsigned long)(arg6); \
3802 _argvec[7] = (unsigned long)(arg7); \
3803 _argvec[8] = (unsigned long)(arg8); \
3804 __asm__ volatile( \
3805 VALGRIND_ALIGN_STACK \
3806 "ldr x0, [%1, #8] \n\t" \
3807 "ldr x1, [%1, #16] \n\t" \
3808 "ldr x2, [%1, #24] \n\t" \
3809 "ldr x3, [%1, #32] \n\t" \
3810 "ldr x4, [%1, #40] \n\t" \
3811 "ldr x5, [%1, #48] \n\t" \
3812 "ldr x6, [%1, #56] \n\t" \
3813 "ldr x7, [%1, #64] \n\t" \
3814 "ldr x8, [%1] \n\t" /* target->x8 */ \
3815 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3816 VALGRIND_RESTORE_STACK \
3817 "mov %0, x0" \
3818 : /*out*/ "=r" (_res) \
3819 : /*in*/ "0" (&_argvec[0]) \
3820 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3821 ); \
3822 lval = (__typeof__(lval)) _res; \
3823 } while (0)
3824
3825#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3826 arg7,arg8,arg9) \
3827 do { \
3828 volatile OrigFn _orig = (orig); \
3829 volatile unsigned long _argvec[10]; \
3830 volatile unsigned long _res; \
3831 _argvec[0] = (unsigned long)_orig.nraddr; \
3832 _argvec[1] = (unsigned long)(arg1); \
3833 _argvec[2] = (unsigned long)(arg2); \
3834 _argvec[3] = (unsigned long)(arg3); \
3835 _argvec[4] = (unsigned long)(arg4); \
3836 _argvec[5] = (unsigned long)(arg5); \
3837 _argvec[6] = (unsigned long)(arg6); \
3838 _argvec[7] = (unsigned long)(arg7); \
3839 _argvec[8] = (unsigned long)(arg8); \
3840 _argvec[9] = (unsigned long)(arg9); \
3841 __asm__ volatile( \
3842 VALGRIND_ALIGN_STACK \
3843 "sub sp, sp, #0x20 \n\t" \
3844 "ldr x0, [%1, #8] \n\t" \
3845 "ldr x1, [%1, #16] \n\t" \
3846 "ldr x2, [%1, #24] \n\t" \
3847 "ldr x3, [%1, #32] \n\t" \
3848 "ldr x4, [%1, #40] \n\t" \
3849 "ldr x5, [%1, #48] \n\t" \
3850 "ldr x6, [%1, #56] \n\t" \
3851 "ldr x7, [%1, #64] \n\t" \
3852 "ldr x8, [%1, #72] \n\t" \
3853 "str x8, [sp, #0] \n\t" \
3854 "ldr x8, [%1] \n\t" /* target->x8 */ \
3855 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3856 VALGRIND_RESTORE_STACK \
3857 "mov %0, x0" \
3858 : /*out*/ "=r" (_res) \
3859 : /*in*/ "0" (&_argvec[0]) \
3860 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3861 ); \
3862 lval = (__typeof__(lval)) _res; \
3863 } while (0)
3864
3865#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3866 arg7,arg8,arg9,arg10) \
3867 do { \
3868 volatile OrigFn _orig = (orig); \
3869 volatile unsigned long _argvec[11]; \
3870 volatile unsigned long _res; \
3871 _argvec[0] = (unsigned long)_orig.nraddr; \
3872 _argvec[1] = (unsigned long)(arg1); \
3873 _argvec[2] = (unsigned long)(arg2); \
3874 _argvec[3] = (unsigned long)(arg3); \
3875 _argvec[4] = (unsigned long)(arg4); \
3876 _argvec[5] = (unsigned long)(arg5); \
3877 _argvec[6] = (unsigned long)(arg6); \
3878 _argvec[7] = (unsigned long)(arg7); \
3879 _argvec[8] = (unsigned long)(arg8); \
3880 _argvec[9] = (unsigned long)(arg9); \
3881 _argvec[10] = (unsigned long)(arg10); \
3882 __asm__ volatile( \
3883 VALGRIND_ALIGN_STACK \
3884 "sub sp, sp, #0x20 \n\t" \
3885 "ldr x0, [%1, #8] \n\t" \
3886 "ldr x1, [%1, #16] \n\t" \
3887 "ldr x2, [%1, #24] \n\t" \
3888 "ldr x3, [%1, #32] \n\t" \
3889 "ldr x4, [%1, #40] \n\t" \
3890 "ldr x5, [%1, #48] \n\t" \
3891 "ldr x6, [%1, #56] \n\t" \
3892 "ldr x7, [%1, #64] \n\t" \
3893 "ldr x8, [%1, #72] \n\t" \
3894 "str x8, [sp, #0] \n\t" \
3895 "ldr x8, [%1, #80] \n\t" \
3896 "str x8, [sp, #8] \n\t" \
3897 "ldr x8, [%1] \n\t" /* target->x8 */ \
3898 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3899 VALGRIND_RESTORE_STACK \
3900 "mov %0, x0" \
3901 : /*out*/ "=r" (_res) \
3902 : /*in*/ "0" (&_argvec[0]) \
3903 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3904 ); \
3905 lval = (__typeof__(lval)) _res; \
3906 } while (0)
3907
3908#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3909 arg7,arg8,arg9,arg10,arg11) \
3910 do { \
3911 volatile OrigFn _orig = (orig); \
3912 volatile unsigned long _argvec[12]; \
3913 volatile unsigned long _res; \
3914 _argvec[0] = (unsigned long)_orig.nraddr; \
3915 _argvec[1] = (unsigned long)(arg1); \
3916 _argvec[2] = (unsigned long)(arg2); \
3917 _argvec[3] = (unsigned long)(arg3); \
3918 _argvec[4] = (unsigned long)(arg4); \
3919 _argvec[5] = (unsigned long)(arg5); \
3920 _argvec[6] = (unsigned long)(arg6); \
3921 _argvec[7] = (unsigned long)(arg7); \
3922 _argvec[8] = (unsigned long)(arg8); \
3923 _argvec[9] = (unsigned long)(arg9); \
3924 _argvec[10] = (unsigned long)(arg10); \
3925 _argvec[11] = (unsigned long)(arg11); \
3926 __asm__ volatile( \
3927 VALGRIND_ALIGN_STACK \
3928 "sub sp, sp, #0x30 \n\t" \
3929 "ldr x0, [%1, #8] \n\t" \
3930 "ldr x1, [%1, #16] \n\t" \
3931 "ldr x2, [%1, #24] \n\t" \
3932 "ldr x3, [%1, #32] \n\t" \
3933 "ldr x4, [%1, #40] \n\t" \
3934 "ldr x5, [%1, #48] \n\t" \
3935 "ldr x6, [%1, #56] \n\t" \
3936 "ldr x7, [%1, #64] \n\t" \
3937 "ldr x8, [%1, #72] \n\t" \
3938 "str x8, [sp, #0] \n\t" \
3939 "ldr x8, [%1, #80] \n\t" \
3940 "str x8, [sp, #8] \n\t" \
3941 "ldr x8, [%1, #88] \n\t" \
3942 "str x8, [sp, #16] \n\t" \
3943 "ldr x8, [%1] \n\t" /* target->x8 */ \
3944 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3945 VALGRIND_RESTORE_STACK \
3946 "mov %0, x0" \
3947 : /*out*/ "=r" (_res) \
3948 : /*in*/ "0" (&_argvec[0]) \
3949 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
3950 ); \
3951 lval = (__typeof__(lval)) _res; \
3952 } while (0)
3953
3954#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3955 arg7,arg8,arg9,arg10,arg11, \
3956 arg12) \
3957 do { \
3958 volatile OrigFn _orig = (orig); \
3959 volatile unsigned long _argvec[13]; \
3960 volatile unsigned long _res; \
3961 _argvec[0] = (unsigned long)_orig.nraddr; \
3962 _argvec[1] = (unsigned long)(arg1); \
3963 _argvec[2] = (unsigned long)(arg2); \
3964 _argvec[3] = (unsigned long)(arg3); \
3965 _argvec[4] = (unsigned long)(arg4); \
3966 _argvec[5] = (unsigned long)(arg5); \
3967 _argvec[6] = (unsigned long)(arg6); \
3968 _argvec[7] = (unsigned long)(arg7); \
3969 _argvec[8] = (unsigned long)(arg8); \
3970 _argvec[9] = (unsigned long)(arg9); \
3971 _argvec[10] = (unsigned long)(arg10); \
3972 _argvec[11] = (unsigned long)(arg11); \
3973 _argvec[12] = (unsigned long)(arg12); \
3974 __asm__ volatile( \
3975 VALGRIND_ALIGN_STACK \
3976 "sub sp, sp, #0x30 \n\t" \
3977 "ldr x0, [%1, #8] \n\t" \
3978 "ldr x1, [%1, #16] \n\t" \
3979 "ldr x2, [%1, #24] \n\t" \
3980 "ldr x3, [%1, #32] \n\t" \
3981 "ldr x4, [%1, #40] \n\t" \
3982 "ldr x5, [%1, #48] \n\t" \
3983 "ldr x6, [%1, #56] \n\t" \
3984 "ldr x7, [%1, #64] \n\t" \
3985 "ldr x8, [%1, #72] \n\t" \
3986 "str x8, [sp, #0] \n\t" \
3987 "ldr x8, [%1, #80] \n\t" \
3988 "str x8, [sp, #8] \n\t" \
3989 "ldr x8, [%1, #88] \n\t" \
3990 "str x8, [sp, #16] \n\t" \
3991 "ldr x8, [%1, #96] \n\t" \
3992 "str x8, [sp, #24] \n\t" \
3993 "ldr x8, [%1] \n\t" /* target->x8 */ \
3994 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
3995 VALGRIND_RESTORE_STACK \
3996 "mov %0, x0" \
3997 : /*out*/ "=r" (_res) \
3998 : /*in*/ "0" (&_argvec[0]) \
3999 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00004000 ); \
4001 lval = (__typeof__(lval)) _res; \
4002 } while (0)
4003
4004#endif /* PLAT_arm64_linux */
4005
sewardjb5b87402011-03-07 16:05:35 +00004006/* ------------------------- s390x-linux ------------------------- */
4007
4008#if defined(PLAT_s390x_linux)
4009
4010/* Similar workaround as amd64 (see above), but we use r11 as frame
4011 pointer and save the old r11 in r7. r11 might be used for
4012 argvec, therefore we copy argvec in r1 since r1 is clobbered
4013 after the call anyway. */
4014#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
4015# define __FRAME_POINTER \
4016 ,"d"(__builtin_dwarf_cfa())
4017# define VALGRIND_CFI_PROLOGUE \
4018 ".cfi_remember_state\n\t" \
4019 "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */ \
4020 "lgr 7,11\n\t" \
4021 "lgr 11,%2\n\t" \
4022 ".cfi_def_cfa r11, 0\n\t"
4023# define VALGRIND_CFI_EPILOGUE \
4024 "lgr 11, 7\n\t" \
4025 ".cfi_restore_state\n\t"
4026#else
4027# define __FRAME_POINTER
4028# define VALGRIND_CFI_PROLOGUE \
4029 "lgr 1,%1\n\t"
4030# define VALGRIND_CFI_EPILOGUE
4031#endif
4032
florian9af940f2012-08-03 03:21:42 +00004033/* Nb: On s390 the stack pointer is properly aligned *at all times*
4034 according to the s390 GCC maintainer. (The ABI specification is not
4035 precise in this regard.) Therefore, VALGRIND_ALIGN_STACK and
4036 VALGRIND_RESTORE_STACK are not defined here. */
sewardjb5b87402011-03-07 16:05:35 +00004037
4038/* These regs are trashed by the hidden call. Note that we overwrite
4039 r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
4040 function a proper return address. All others are ABI defined call
4041 clobbers. */
4042#define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \
4043 "f0","f1","f2","f3","f4","f5","f6","f7"
4044
florian9af940f2012-08-03 03:21:42 +00004045/* Nb: Although r11 is modified in the asm snippets below (inside
4046 VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for
4047 two reasons:
4048 (1) r11 is restored in VALGRIND_CFI_EPILOGUE, so effectively it is not
4049 modified
4050 (2) GCC will complain that r11 cannot appear inside a clobber section,
4051 when compiled with -O -fno-omit-frame-pointer
4052 */
sewardjb5b87402011-03-07 16:05:35 +00004053
4054#define CALL_FN_W_v(lval, orig) \
4055 do { \
4056 volatile OrigFn _orig = (orig); \
4057 volatile unsigned long _argvec[1]; \
4058 volatile unsigned long _res; \
4059 _argvec[0] = (unsigned long)_orig.nraddr; \
4060 __asm__ volatile( \
4061 VALGRIND_CFI_PROLOGUE \
4062 "aghi 15,-160\n\t" \
4063 "lg 1, 0(1)\n\t" /* target->r1 */ \
4064 VALGRIND_CALL_NOREDIR_R1 \
4065 "lgr %0, 2\n\t" \
4066 "aghi 15,160\n\t" \
4067 VALGRIND_CFI_EPILOGUE \
4068 : /*out*/ "=d" (_res) \
4069 : /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \
4070 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4071 ); \
4072 lval = (__typeof__(lval)) _res; \
4073 } while (0)
4074
4075/* The call abi has the arguments in r2-r6 and stack */
4076#define CALL_FN_W_W(lval, orig, arg1) \
4077 do { \
4078 volatile OrigFn _orig = (orig); \
4079 volatile unsigned long _argvec[2]; \
4080 volatile unsigned long _res; \
4081 _argvec[0] = (unsigned long)_orig.nraddr; \
4082 _argvec[1] = (unsigned long)arg1; \
4083 __asm__ volatile( \
4084 VALGRIND_CFI_PROLOGUE \
4085 "aghi 15,-160\n\t" \
4086 "lg 2, 8(1)\n\t" \
4087 "lg 1, 0(1)\n\t" \
4088 VALGRIND_CALL_NOREDIR_R1 \
4089 "lgr %0, 2\n\t" \
4090 "aghi 15,160\n\t" \
4091 VALGRIND_CFI_EPILOGUE \
4092 : /*out*/ "=d" (_res) \
4093 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4094 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4095 ); \
4096 lval = (__typeof__(lval)) _res; \
4097 } while (0)
4098
4099#define CALL_FN_W_WW(lval, orig, arg1, arg2) \
4100 do { \
4101 volatile OrigFn _orig = (orig); \
4102 volatile unsigned long _argvec[3]; \
4103 volatile unsigned long _res; \
4104 _argvec[0] = (unsigned long)_orig.nraddr; \
4105 _argvec[1] = (unsigned long)arg1; \
4106 _argvec[2] = (unsigned long)arg2; \
4107 __asm__ volatile( \
4108 VALGRIND_CFI_PROLOGUE \
4109 "aghi 15,-160\n\t" \
4110 "lg 2, 8(1)\n\t" \
4111 "lg 3,16(1)\n\t" \
4112 "lg 1, 0(1)\n\t" \
4113 VALGRIND_CALL_NOREDIR_R1 \
4114 "lgr %0, 2\n\t" \
4115 "aghi 15,160\n\t" \
4116 VALGRIND_CFI_EPILOGUE \
4117 : /*out*/ "=d" (_res) \
4118 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4119 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4120 ); \
4121 lval = (__typeof__(lval)) _res; \
4122 } while (0)
4123
4124#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \
4125 do { \
4126 volatile OrigFn _orig = (orig); \
4127 volatile unsigned long _argvec[4]; \
4128 volatile unsigned long _res; \
4129 _argvec[0] = (unsigned long)_orig.nraddr; \
4130 _argvec[1] = (unsigned long)arg1; \
4131 _argvec[2] = (unsigned long)arg2; \
4132 _argvec[3] = (unsigned long)arg3; \
4133 __asm__ volatile( \
4134 VALGRIND_CFI_PROLOGUE \
4135 "aghi 15,-160\n\t" \
4136 "lg 2, 8(1)\n\t" \
4137 "lg 3,16(1)\n\t" \
4138 "lg 4,24(1)\n\t" \
4139 "lg 1, 0(1)\n\t" \
4140 VALGRIND_CALL_NOREDIR_R1 \
4141 "lgr %0, 2\n\t" \
4142 "aghi 15,160\n\t" \
4143 VALGRIND_CFI_EPILOGUE \
4144 : /*out*/ "=d" (_res) \
4145 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4146 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4147 ); \
4148 lval = (__typeof__(lval)) _res; \
4149 } while (0)
4150
4151#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \
4152 do { \
4153 volatile OrigFn _orig = (orig); \
4154 volatile unsigned long _argvec[5]; \
4155 volatile unsigned long _res; \
4156 _argvec[0] = (unsigned long)_orig.nraddr; \
4157 _argvec[1] = (unsigned long)arg1; \
4158 _argvec[2] = (unsigned long)arg2; \
4159 _argvec[3] = (unsigned long)arg3; \
4160 _argvec[4] = (unsigned long)arg4; \
4161 __asm__ volatile( \
4162 VALGRIND_CFI_PROLOGUE \
4163 "aghi 15,-160\n\t" \
4164 "lg 2, 8(1)\n\t" \
4165 "lg 3,16(1)\n\t" \
4166 "lg 4,24(1)\n\t" \
4167 "lg 5,32(1)\n\t" \
4168 "lg 1, 0(1)\n\t" \
4169 VALGRIND_CALL_NOREDIR_R1 \
4170 "lgr %0, 2\n\t" \
4171 "aghi 15,160\n\t" \
4172 VALGRIND_CFI_EPILOGUE \
4173 : /*out*/ "=d" (_res) \
4174 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4175 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4176 ); \
4177 lval = (__typeof__(lval)) _res; \
4178 } while (0)
4179
4180#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \
4181 do { \
4182 volatile OrigFn _orig = (orig); \
4183 volatile unsigned long _argvec[6]; \
4184 volatile unsigned long _res; \
4185 _argvec[0] = (unsigned long)_orig.nraddr; \
4186 _argvec[1] = (unsigned long)arg1; \
4187 _argvec[2] = (unsigned long)arg2; \
4188 _argvec[3] = (unsigned long)arg3; \
4189 _argvec[4] = (unsigned long)arg4; \
4190 _argvec[5] = (unsigned long)arg5; \
4191 __asm__ volatile( \
4192 VALGRIND_CFI_PROLOGUE \
4193 "aghi 15,-160\n\t" \
4194 "lg 2, 8(1)\n\t" \
4195 "lg 3,16(1)\n\t" \
4196 "lg 4,24(1)\n\t" \
4197 "lg 5,32(1)\n\t" \
4198 "lg 6,40(1)\n\t" \
4199 "lg 1, 0(1)\n\t" \
4200 VALGRIND_CALL_NOREDIR_R1 \
4201 "lgr %0, 2\n\t" \
4202 "aghi 15,160\n\t" \
4203 VALGRIND_CFI_EPILOGUE \
4204 : /*out*/ "=d" (_res) \
4205 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4206 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4207 ); \
4208 lval = (__typeof__(lval)) _res; \
4209 } while (0)
4210
4211#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4212 arg6) \
4213 do { \
4214 volatile OrigFn _orig = (orig); \
4215 volatile unsigned long _argvec[7]; \
4216 volatile unsigned long _res; \
4217 _argvec[0] = (unsigned long)_orig.nraddr; \
4218 _argvec[1] = (unsigned long)arg1; \
4219 _argvec[2] = (unsigned long)arg2; \
4220 _argvec[3] = (unsigned long)arg3; \
4221 _argvec[4] = (unsigned long)arg4; \
4222 _argvec[5] = (unsigned long)arg5; \
4223 _argvec[6] = (unsigned long)arg6; \
4224 __asm__ volatile( \
4225 VALGRIND_CFI_PROLOGUE \
4226 "aghi 15,-168\n\t" \
4227 "lg 2, 8(1)\n\t" \
4228 "lg 3,16(1)\n\t" \
4229 "lg 4,24(1)\n\t" \
4230 "lg 5,32(1)\n\t" \
4231 "lg 6,40(1)\n\t" \
4232 "mvc 160(8,15), 48(1)\n\t" \
4233 "lg 1, 0(1)\n\t" \
4234 VALGRIND_CALL_NOREDIR_R1 \
4235 "lgr %0, 2\n\t" \
4236 "aghi 15,168\n\t" \
4237 VALGRIND_CFI_EPILOGUE \
4238 : /*out*/ "=d" (_res) \
4239 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4240 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4241 ); \
4242 lval = (__typeof__(lval)) _res; \
4243 } while (0)
4244
4245#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4246 arg6, arg7) \
4247 do { \
4248 volatile OrigFn _orig = (orig); \
4249 volatile unsigned long _argvec[8]; \
4250 volatile unsigned long _res; \
4251 _argvec[0] = (unsigned long)_orig.nraddr; \
4252 _argvec[1] = (unsigned long)arg1; \
4253 _argvec[2] = (unsigned long)arg2; \
4254 _argvec[3] = (unsigned long)arg3; \
4255 _argvec[4] = (unsigned long)arg4; \
4256 _argvec[5] = (unsigned long)arg5; \
4257 _argvec[6] = (unsigned long)arg6; \
4258 _argvec[7] = (unsigned long)arg7; \
4259 __asm__ volatile( \
4260 VALGRIND_CFI_PROLOGUE \
4261 "aghi 15,-176\n\t" \
4262 "lg 2, 8(1)\n\t" \
4263 "lg 3,16(1)\n\t" \
4264 "lg 4,24(1)\n\t" \
4265 "lg 5,32(1)\n\t" \
4266 "lg 6,40(1)\n\t" \
4267 "mvc 160(8,15), 48(1)\n\t" \
4268 "mvc 168(8,15), 56(1)\n\t" \
4269 "lg 1, 0(1)\n\t" \
4270 VALGRIND_CALL_NOREDIR_R1 \
4271 "lgr %0, 2\n\t" \
4272 "aghi 15,176\n\t" \
4273 VALGRIND_CFI_EPILOGUE \
4274 : /*out*/ "=d" (_res) \
4275 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4276 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4277 ); \
4278 lval = (__typeof__(lval)) _res; \
4279 } while (0)
4280
4281#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4282 arg6, arg7 ,arg8) \
4283 do { \
4284 volatile OrigFn _orig = (orig); \
4285 volatile unsigned long _argvec[9]; \
4286 volatile unsigned long _res; \
4287 _argvec[0] = (unsigned long)_orig.nraddr; \
4288 _argvec[1] = (unsigned long)arg1; \
4289 _argvec[2] = (unsigned long)arg2; \
4290 _argvec[3] = (unsigned long)arg3; \
4291 _argvec[4] = (unsigned long)arg4; \
4292 _argvec[5] = (unsigned long)arg5; \
4293 _argvec[6] = (unsigned long)arg6; \
4294 _argvec[7] = (unsigned long)arg7; \
4295 _argvec[8] = (unsigned long)arg8; \
4296 __asm__ volatile( \
4297 VALGRIND_CFI_PROLOGUE \
4298 "aghi 15,-184\n\t" \
4299 "lg 2, 8(1)\n\t" \
4300 "lg 3,16(1)\n\t" \
4301 "lg 4,24(1)\n\t" \
4302 "lg 5,32(1)\n\t" \
4303 "lg 6,40(1)\n\t" \
4304 "mvc 160(8,15), 48(1)\n\t" \
4305 "mvc 168(8,15), 56(1)\n\t" \
4306 "mvc 176(8,15), 64(1)\n\t" \
4307 "lg 1, 0(1)\n\t" \
4308 VALGRIND_CALL_NOREDIR_R1 \
4309 "lgr %0, 2\n\t" \
4310 "aghi 15,184\n\t" \
4311 VALGRIND_CFI_EPILOGUE \
4312 : /*out*/ "=d" (_res) \
4313 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4314 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4315 ); \
4316 lval = (__typeof__(lval)) _res; \
4317 } while (0)
4318
4319#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4320 arg6, arg7 ,arg8, arg9) \
4321 do { \
4322 volatile OrigFn _orig = (orig); \
4323 volatile unsigned long _argvec[10]; \
4324 volatile unsigned long _res; \
4325 _argvec[0] = (unsigned long)_orig.nraddr; \
4326 _argvec[1] = (unsigned long)arg1; \
4327 _argvec[2] = (unsigned long)arg2; \
4328 _argvec[3] = (unsigned long)arg3; \
4329 _argvec[4] = (unsigned long)arg4; \
4330 _argvec[5] = (unsigned long)arg5; \
4331 _argvec[6] = (unsigned long)arg6; \
4332 _argvec[7] = (unsigned long)arg7; \
4333 _argvec[8] = (unsigned long)arg8; \
4334 _argvec[9] = (unsigned long)arg9; \
4335 __asm__ volatile( \
4336 VALGRIND_CFI_PROLOGUE \
4337 "aghi 15,-192\n\t" \
4338 "lg 2, 8(1)\n\t" \
4339 "lg 3,16(1)\n\t" \
4340 "lg 4,24(1)\n\t" \
4341 "lg 5,32(1)\n\t" \
4342 "lg 6,40(1)\n\t" \
4343 "mvc 160(8,15), 48(1)\n\t" \
4344 "mvc 168(8,15), 56(1)\n\t" \
4345 "mvc 176(8,15), 64(1)\n\t" \
4346 "mvc 184(8,15), 72(1)\n\t" \
4347 "lg 1, 0(1)\n\t" \
4348 VALGRIND_CALL_NOREDIR_R1 \
4349 "lgr %0, 2\n\t" \
4350 "aghi 15,192\n\t" \
4351 VALGRIND_CFI_EPILOGUE \
4352 : /*out*/ "=d" (_res) \
4353 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4354 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4355 ); \
4356 lval = (__typeof__(lval)) _res; \
4357 } while (0)
4358
4359#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4360 arg6, arg7 ,arg8, arg9, arg10) \
4361 do { \
4362 volatile OrigFn _orig = (orig); \
4363 volatile unsigned long _argvec[11]; \
4364 volatile unsigned long _res; \
4365 _argvec[0] = (unsigned long)_orig.nraddr; \
4366 _argvec[1] = (unsigned long)arg1; \
4367 _argvec[2] = (unsigned long)arg2; \
4368 _argvec[3] = (unsigned long)arg3; \
4369 _argvec[4] = (unsigned long)arg4; \
4370 _argvec[5] = (unsigned long)arg5; \
4371 _argvec[6] = (unsigned long)arg6; \
4372 _argvec[7] = (unsigned long)arg7; \
4373 _argvec[8] = (unsigned long)arg8; \
4374 _argvec[9] = (unsigned long)arg9; \
4375 _argvec[10] = (unsigned long)arg10; \
4376 __asm__ volatile( \
4377 VALGRIND_CFI_PROLOGUE \
4378 "aghi 15,-200\n\t" \
4379 "lg 2, 8(1)\n\t" \
4380 "lg 3,16(1)\n\t" \
4381 "lg 4,24(1)\n\t" \
4382 "lg 5,32(1)\n\t" \
4383 "lg 6,40(1)\n\t" \
4384 "mvc 160(8,15), 48(1)\n\t" \
4385 "mvc 168(8,15), 56(1)\n\t" \
4386 "mvc 176(8,15), 64(1)\n\t" \
4387 "mvc 184(8,15), 72(1)\n\t" \
4388 "mvc 192(8,15), 80(1)\n\t" \
4389 "lg 1, 0(1)\n\t" \
4390 VALGRIND_CALL_NOREDIR_R1 \
4391 "lgr %0, 2\n\t" \
4392 "aghi 15,200\n\t" \
4393 VALGRIND_CFI_EPILOGUE \
4394 : /*out*/ "=d" (_res) \
4395 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4396 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4397 ); \
4398 lval = (__typeof__(lval)) _res; \
4399 } while (0)
4400
4401#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4402 arg6, arg7 ,arg8, arg9, arg10, arg11) \
4403 do { \
4404 volatile OrigFn _orig = (orig); \
4405 volatile unsigned long _argvec[12]; \
4406 volatile unsigned long _res; \
4407 _argvec[0] = (unsigned long)_orig.nraddr; \
4408 _argvec[1] = (unsigned long)arg1; \
4409 _argvec[2] = (unsigned long)arg2; \
4410 _argvec[3] = (unsigned long)arg3; \
4411 _argvec[4] = (unsigned long)arg4; \
4412 _argvec[5] = (unsigned long)arg5; \
4413 _argvec[6] = (unsigned long)arg6; \
4414 _argvec[7] = (unsigned long)arg7; \
4415 _argvec[8] = (unsigned long)arg8; \
4416 _argvec[9] = (unsigned long)arg9; \
4417 _argvec[10] = (unsigned long)arg10; \
4418 _argvec[11] = (unsigned long)arg11; \
4419 __asm__ volatile( \
4420 VALGRIND_CFI_PROLOGUE \
4421 "aghi 15,-208\n\t" \
4422 "lg 2, 8(1)\n\t" \
4423 "lg 3,16(1)\n\t" \
4424 "lg 4,24(1)\n\t" \
4425 "lg 5,32(1)\n\t" \
4426 "lg 6,40(1)\n\t" \
4427 "mvc 160(8,15), 48(1)\n\t" \
4428 "mvc 168(8,15), 56(1)\n\t" \
4429 "mvc 176(8,15), 64(1)\n\t" \
4430 "mvc 184(8,15), 72(1)\n\t" \
4431 "mvc 192(8,15), 80(1)\n\t" \
4432 "mvc 200(8,15), 88(1)\n\t" \
4433 "lg 1, 0(1)\n\t" \
4434 VALGRIND_CALL_NOREDIR_R1 \
4435 "lgr %0, 2\n\t" \
4436 "aghi 15,208\n\t" \
4437 VALGRIND_CFI_EPILOGUE \
4438 : /*out*/ "=d" (_res) \
4439 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4440 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4441 ); \
4442 lval = (__typeof__(lval)) _res; \
4443 } while (0)
4444
4445#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4446 arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\
4447 do { \
4448 volatile OrigFn _orig = (orig); \
4449 volatile unsigned long _argvec[13]; \
4450 volatile unsigned long _res; \
4451 _argvec[0] = (unsigned long)_orig.nraddr; \
4452 _argvec[1] = (unsigned long)arg1; \
4453 _argvec[2] = (unsigned long)arg2; \
4454 _argvec[3] = (unsigned long)arg3; \
4455 _argvec[4] = (unsigned long)arg4; \
4456 _argvec[5] = (unsigned long)arg5; \
4457 _argvec[6] = (unsigned long)arg6; \
4458 _argvec[7] = (unsigned long)arg7; \
4459 _argvec[8] = (unsigned long)arg8; \
4460 _argvec[9] = (unsigned long)arg9; \
4461 _argvec[10] = (unsigned long)arg10; \
4462 _argvec[11] = (unsigned long)arg11; \
4463 _argvec[12] = (unsigned long)arg12; \
4464 __asm__ volatile( \
4465 VALGRIND_CFI_PROLOGUE \
4466 "aghi 15,-216\n\t" \
4467 "lg 2, 8(1)\n\t" \
4468 "lg 3,16(1)\n\t" \
4469 "lg 4,24(1)\n\t" \
4470 "lg 5,32(1)\n\t" \
4471 "lg 6,40(1)\n\t" \
4472 "mvc 160(8,15), 48(1)\n\t" \
4473 "mvc 168(8,15), 56(1)\n\t" \
4474 "mvc 176(8,15), 64(1)\n\t" \
4475 "mvc 184(8,15), 72(1)\n\t" \
4476 "mvc 192(8,15), 80(1)\n\t" \
4477 "mvc 200(8,15), 88(1)\n\t" \
4478 "mvc 208(8,15), 96(1)\n\t" \
4479 "lg 1, 0(1)\n\t" \
4480 VALGRIND_CALL_NOREDIR_R1 \
4481 "lgr %0, 2\n\t" \
4482 "aghi 15,216\n\t" \
4483 VALGRIND_CFI_EPILOGUE \
4484 : /*out*/ "=d" (_res) \
4485 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4486 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4487 ); \
4488 lval = (__typeof__(lval)) _res; \
4489 } while (0)
4490
4491
4492#endif /* PLAT_s390x_linux */
4493
petarj4df0bfc2013-02-27 23:17:33 +00004494/* ------------------------- mips32-linux ----------------------- */
sewardj5db15402012-06-07 09:13:21 +00004495
4496#if defined(PLAT_mips32_linux)
4497
4498/* These regs are trashed by the hidden call. */
4499#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \
4500"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
4501"$25", "$31"
4502
4503/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
4504 long) == 4. */
4505
4506#define CALL_FN_W_v(lval, orig) \
4507 do { \
4508 volatile OrigFn _orig = (orig); \
4509 volatile unsigned long _argvec[1]; \
4510 volatile unsigned long _res; \
4511 _argvec[0] = (unsigned long)_orig.nraddr; \
4512 __asm__ volatile( \
4513 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004514 "sw $28, 0($29) \n\t" \
4515 "sw $31, 4($29) \n\t" \
4516 "subu $29, $29, 16 \n\t" \
4517 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004518 VALGRIND_CALL_NOREDIR_T9 \
4519 "addu $29, $29, 16\n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004520 "lw $28, 0($29) \n\t" \
4521 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004522 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004523 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004524 : /*out*/ "=r" (_res) \
4525 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004526 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004527 ); \
4528 lval = (__typeof__(lval)) _res; \
4529 } while (0)
4530
4531#define CALL_FN_W_W(lval, orig, arg1) \
4532 do { \
4533 volatile OrigFn _orig = (orig); \
4534 volatile unsigned long _argvec[2]; \
4535 volatile unsigned long _res; \
4536 _argvec[0] = (unsigned long)_orig.nraddr; \
4537 _argvec[1] = (unsigned long)(arg1); \
4538 __asm__ volatile( \
4539 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004540 "sw $28, 0($29) \n\t" \
4541 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004542 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004543 "lw $4, 4(%1) \n\t" /* arg1*/ \
4544 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004545 VALGRIND_CALL_NOREDIR_T9 \
4546 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004547 "lw $28, 0($29) \n\t" \
4548 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004549 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004550 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004551 : /*out*/ "=r" (_res) \
petarj4df0bfc2013-02-27 23:17:33 +00004552 : /*in*/ "0" (&_argvec[0]) \
4553 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004554 ); \
4555 lval = (__typeof__(lval)) _res; \
4556 } while (0)
4557
4558#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
4559 do { \
4560 volatile OrigFn _orig = (orig); \
4561 volatile unsigned long _argvec[3]; \
4562 volatile unsigned long _res; \
4563 _argvec[0] = (unsigned long)_orig.nraddr; \
4564 _argvec[1] = (unsigned long)(arg1); \
4565 _argvec[2] = (unsigned long)(arg2); \
4566 __asm__ volatile( \
4567 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004568 "sw $28, 0($29) \n\t" \
4569 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004570 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004571 "lw $4, 4(%1) \n\t" \
4572 "lw $5, 8(%1) \n\t" \
4573 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004574 VALGRIND_CALL_NOREDIR_T9 \
4575 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004576 "lw $28, 0($29) \n\t" \
4577 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004578 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004579 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004580 : /*out*/ "=r" (_res) \
4581 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004582 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004583 ); \
4584 lval = (__typeof__(lval)) _res; \
4585 } while (0)
4586
4587#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
4588 do { \
4589 volatile OrigFn _orig = (orig); \
4590 volatile unsigned long _argvec[4]; \
4591 volatile unsigned long _res; \
4592 _argvec[0] = (unsigned long)_orig.nraddr; \
4593 _argvec[1] = (unsigned long)(arg1); \
4594 _argvec[2] = (unsigned long)(arg2); \
4595 _argvec[3] = (unsigned long)(arg3); \
4596 __asm__ volatile( \
4597 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004598 "sw $28, 0($29) \n\t" \
4599 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004600 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004601 "lw $4, 4(%1) \n\t" \
4602 "lw $5, 8(%1) \n\t" \
4603 "lw $6, 12(%1) \n\t" \
4604 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004605 VALGRIND_CALL_NOREDIR_T9 \
4606 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004607 "lw $28, 0($29) \n\t" \
4608 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004609 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004610 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004611 : /*out*/ "=r" (_res) \
4612 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004613 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004614 ); \
4615 lval = (__typeof__(lval)) _res; \
4616 } while (0)
4617
4618#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
4619 do { \
4620 volatile OrigFn _orig = (orig); \
4621 volatile unsigned long _argvec[5]; \
4622 volatile unsigned long _res; \
4623 _argvec[0] = (unsigned long)_orig.nraddr; \
4624 _argvec[1] = (unsigned long)(arg1); \
4625 _argvec[2] = (unsigned long)(arg2); \
4626 _argvec[3] = (unsigned long)(arg3); \
4627 _argvec[4] = (unsigned long)(arg4); \
4628 __asm__ volatile( \
4629 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004630 "sw $28, 0($29) \n\t" \
4631 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004632 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004633 "lw $4, 4(%1) \n\t" \
4634 "lw $5, 8(%1) \n\t" \
4635 "lw $6, 12(%1) \n\t" \
4636 "lw $7, 16(%1) \n\t" \
4637 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004638 VALGRIND_CALL_NOREDIR_T9 \
4639 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004640 "lw $28, 0($29) \n\t" \
4641 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004642 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004643 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004644 : /*out*/ "=r" (_res) \
4645 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004646 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004647 ); \
4648 lval = (__typeof__(lval)) _res; \
4649 } while (0)
4650
4651#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
4652 do { \
4653 volatile OrigFn _orig = (orig); \
4654 volatile unsigned long _argvec[6]; \
4655 volatile unsigned long _res; \
4656 _argvec[0] = (unsigned long)_orig.nraddr; \
4657 _argvec[1] = (unsigned long)(arg1); \
4658 _argvec[2] = (unsigned long)(arg2); \
4659 _argvec[3] = (unsigned long)(arg3); \
4660 _argvec[4] = (unsigned long)(arg4); \
4661 _argvec[5] = (unsigned long)(arg5); \
4662 __asm__ volatile( \
4663 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004664 "sw $28, 0($29) \n\t" \
4665 "sw $31, 4($29) \n\t" \
4666 "lw $4, 20(%1) \n\t" \
4667 "subu $29, $29, 24\n\t" \
4668 "sw $4, 16($29) \n\t" \
4669 "lw $4, 4(%1) \n\t" \
4670 "lw $5, 8(%1) \n\t" \
4671 "lw $6, 12(%1) \n\t" \
4672 "lw $7, 16(%1) \n\t" \
4673 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004674 VALGRIND_CALL_NOREDIR_T9 \
4675 "addu $29, $29, 24 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004676 "lw $28, 0($29) \n\t" \
4677 "lw $31, 4($29) \n\t" \
4678 "addu $29, $29, 8 \n\t" \
4679 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004680 : /*out*/ "=r" (_res) \
4681 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004682 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004683 ); \
4684 lval = (__typeof__(lval)) _res; \
4685 } while (0)
4686#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
4687 do { \
4688 volatile OrigFn _orig = (orig); \
4689 volatile unsigned long _argvec[7]; \
4690 volatile unsigned long _res; \
4691 _argvec[0] = (unsigned long)_orig.nraddr; \
4692 _argvec[1] = (unsigned long)(arg1); \
4693 _argvec[2] = (unsigned long)(arg2); \
4694 _argvec[3] = (unsigned long)(arg3); \
4695 _argvec[4] = (unsigned long)(arg4); \
4696 _argvec[5] = (unsigned long)(arg5); \
4697 _argvec[6] = (unsigned long)(arg6); \
4698 __asm__ volatile( \
4699 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004700 "sw $28, 0($29) \n\t" \
4701 "sw $31, 4($29) \n\t" \
4702 "lw $4, 20(%1) \n\t" \
4703 "subu $29, $29, 32\n\t" \
4704 "sw $4, 16($29) \n\t" \
4705 "lw $4, 24(%1) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00004706 "nop\n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004707 "sw $4, 20($29) \n\t" \
4708 "lw $4, 4(%1) \n\t" \
4709 "lw $5, 8(%1) \n\t" \
4710 "lw $6, 12(%1) \n\t" \
4711 "lw $7, 16(%1) \n\t" \
4712 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004713 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00004714 "addu $29, $29, 32 \n\t" \
4715 "lw $28, 0($29) \n\t" \
4716 "lw $31, 4($29) \n\t" \
4717 "addu $29, $29, 8 \n\t" \
4718 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004719 : /*out*/ "=r" (_res) \
4720 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004721 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004722 ); \
4723 lval = (__typeof__(lval)) _res; \
4724 } while (0)
4725
4726#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4727 arg7) \
4728 do { \
4729 volatile OrigFn _orig = (orig); \
4730 volatile unsigned long _argvec[8]; \
4731 volatile unsigned long _res; \
4732 _argvec[0] = (unsigned long)_orig.nraddr; \
4733 _argvec[1] = (unsigned long)(arg1); \
4734 _argvec[2] = (unsigned long)(arg2); \
4735 _argvec[3] = (unsigned long)(arg3); \
4736 _argvec[4] = (unsigned long)(arg4); \
4737 _argvec[5] = (unsigned long)(arg5); \
4738 _argvec[6] = (unsigned long)(arg6); \
4739 _argvec[7] = (unsigned long)(arg7); \
4740 __asm__ volatile( \
4741 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004742 "sw $28, 0($29) \n\t" \
4743 "sw $31, 4($29) \n\t" \
4744 "lw $4, 20(%1) \n\t" \
4745 "subu $29, $29, 32\n\t" \
4746 "sw $4, 16($29) \n\t" \
4747 "lw $4, 24(%1) \n\t" \
4748 "sw $4, 20($29) \n\t" \
4749 "lw $4, 28(%1) \n\t" \
4750 "sw $4, 24($29) \n\t" \
4751 "lw $4, 4(%1) \n\t" \
4752 "lw $5, 8(%1) \n\t" \
4753 "lw $6, 12(%1) \n\t" \
4754 "lw $7, 16(%1) \n\t" \
4755 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004756 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00004757 "addu $29, $29, 32 \n\t" \
4758 "lw $28, 0($29) \n\t" \
4759 "lw $31, 4($29) \n\t" \
4760 "addu $29, $29, 8 \n\t" \
4761 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004762 : /*out*/ "=r" (_res) \
4763 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004764 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004765 ); \
4766 lval = (__typeof__(lval)) _res; \
4767 } while (0)
4768
4769#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4770 arg7,arg8) \
4771 do { \
4772 volatile OrigFn _orig = (orig); \
4773 volatile unsigned long _argvec[9]; \
4774 volatile unsigned long _res; \
4775 _argvec[0] = (unsigned long)_orig.nraddr; \
4776 _argvec[1] = (unsigned long)(arg1); \
4777 _argvec[2] = (unsigned long)(arg2); \
4778 _argvec[3] = (unsigned long)(arg3); \
4779 _argvec[4] = (unsigned long)(arg4); \
4780 _argvec[5] = (unsigned long)(arg5); \
4781 _argvec[6] = (unsigned long)(arg6); \
4782 _argvec[7] = (unsigned long)(arg7); \
4783 _argvec[8] = (unsigned long)(arg8); \
4784 __asm__ volatile( \
4785 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004786 "sw $28, 0($29) \n\t" \
4787 "sw $31, 4($29) \n\t" \
4788 "lw $4, 20(%1) \n\t" \
4789 "subu $29, $29, 40\n\t" \
4790 "sw $4, 16($29) \n\t" \
4791 "lw $4, 24(%1) \n\t" \
4792 "sw $4, 20($29) \n\t" \
4793 "lw $4, 28(%1) \n\t" \
4794 "sw $4, 24($29) \n\t" \
4795 "lw $4, 32(%1) \n\t" \
4796 "sw $4, 28($29) \n\t" \
4797 "lw $4, 4(%1) \n\t" \
4798 "lw $5, 8(%1) \n\t" \
4799 "lw $6, 12(%1) \n\t" \
4800 "lw $7, 16(%1) \n\t" \
4801 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004802 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00004803 "addu $29, $29, 40 \n\t" \
4804 "lw $28, 0($29) \n\t" \
4805 "lw $31, 4($29) \n\t" \
4806 "addu $29, $29, 8 \n\t" \
4807 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004808 : /*out*/ "=r" (_res) \
4809 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004810 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004811 ); \
4812 lval = (__typeof__(lval)) _res; \
4813 } while (0)
4814
4815#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4816 arg7,arg8,arg9) \
4817 do { \
4818 volatile OrigFn _orig = (orig); \
4819 volatile unsigned long _argvec[10]; \
4820 volatile unsigned long _res; \
4821 _argvec[0] = (unsigned long)_orig.nraddr; \
4822 _argvec[1] = (unsigned long)(arg1); \
4823 _argvec[2] = (unsigned long)(arg2); \
4824 _argvec[3] = (unsigned long)(arg3); \
4825 _argvec[4] = (unsigned long)(arg4); \
4826 _argvec[5] = (unsigned long)(arg5); \
4827 _argvec[6] = (unsigned long)(arg6); \
4828 _argvec[7] = (unsigned long)(arg7); \
4829 _argvec[8] = (unsigned long)(arg8); \
4830 _argvec[9] = (unsigned long)(arg9); \
4831 __asm__ volatile( \
4832 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004833 "sw $28, 0($29) \n\t" \
4834 "sw $31, 4($29) \n\t" \
4835 "lw $4, 20(%1) \n\t" \
4836 "subu $29, $29, 40\n\t" \
4837 "sw $4, 16($29) \n\t" \
4838 "lw $4, 24(%1) \n\t" \
4839 "sw $4, 20($29) \n\t" \
4840 "lw $4, 28(%1) \n\t" \
4841 "sw $4, 24($29) \n\t" \
4842 "lw $4, 32(%1) \n\t" \
4843 "sw $4, 28($29) \n\t" \
4844 "lw $4, 36(%1) \n\t" \
4845 "sw $4, 32($29) \n\t" \
4846 "lw $4, 4(%1) \n\t" \
4847 "lw $5, 8(%1) \n\t" \
4848 "lw $6, 12(%1) \n\t" \
4849 "lw $7, 16(%1) \n\t" \
4850 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004851 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00004852 "addu $29, $29, 40 \n\t" \
4853 "lw $28, 0($29) \n\t" \
4854 "lw $31, 4($29) \n\t" \
4855 "addu $29, $29, 8 \n\t" \
4856 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004857 : /*out*/ "=r" (_res) \
4858 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004859 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004860 ); \
4861 lval = (__typeof__(lval)) _res; \
4862 } while (0)
4863
4864#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4865 arg7,arg8,arg9,arg10) \
4866 do { \
4867 volatile OrigFn _orig = (orig); \
4868 volatile unsigned long _argvec[11]; \
4869 volatile unsigned long _res; \
4870 _argvec[0] = (unsigned long)_orig.nraddr; \
4871 _argvec[1] = (unsigned long)(arg1); \
4872 _argvec[2] = (unsigned long)(arg2); \
4873 _argvec[3] = (unsigned long)(arg3); \
4874 _argvec[4] = (unsigned long)(arg4); \
4875 _argvec[5] = (unsigned long)(arg5); \
4876 _argvec[6] = (unsigned long)(arg6); \
4877 _argvec[7] = (unsigned long)(arg7); \
4878 _argvec[8] = (unsigned long)(arg8); \
4879 _argvec[9] = (unsigned long)(arg9); \
4880 _argvec[10] = (unsigned long)(arg10); \
4881 __asm__ volatile( \
4882 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004883 "sw $28, 0($29) \n\t" \
4884 "sw $31, 4($29) \n\t" \
4885 "lw $4, 20(%1) \n\t" \
4886 "subu $29, $29, 48\n\t" \
4887 "sw $4, 16($29) \n\t" \
4888 "lw $4, 24(%1) \n\t" \
4889 "sw $4, 20($29) \n\t" \
4890 "lw $4, 28(%1) \n\t" \
4891 "sw $4, 24($29) \n\t" \
4892 "lw $4, 32(%1) \n\t" \
4893 "sw $4, 28($29) \n\t" \
4894 "lw $4, 36(%1) \n\t" \
4895 "sw $4, 32($29) \n\t" \
4896 "lw $4, 40(%1) \n\t" \
4897 "sw $4, 36($29) \n\t" \
4898 "lw $4, 4(%1) \n\t" \
4899 "lw $5, 8(%1) \n\t" \
4900 "lw $6, 12(%1) \n\t" \
4901 "lw $7, 16(%1) \n\t" \
4902 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004903 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00004904 "addu $29, $29, 48 \n\t" \
4905 "lw $28, 0($29) \n\t" \
4906 "lw $31, 4($29) \n\t" \
4907 "addu $29, $29, 8 \n\t" \
4908 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004909 : /*out*/ "=r" (_res) \
4910 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004911 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004912 ); \
4913 lval = (__typeof__(lval)) _res; \
4914 } while (0)
4915
4916#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
4917 arg6,arg7,arg8,arg9,arg10, \
4918 arg11) \
4919 do { \
4920 volatile OrigFn _orig = (orig); \
4921 volatile unsigned long _argvec[12]; \
4922 volatile unsigned long _res; \
4923 _argvec[0] = (unsigned long)_orig.nraddr; \
4924 _argvec[1] = (unsigned long)(arg1); \
4925 _argvec[2] = (unsigned long)(arg2); \
4926 _argvec[3] = (unsigned long)(arg3); \
4927 _argvec[4] = (unsigned long)(arg4); \
4928 _argvec[5] = (unsigned long)(arg5); \
4929 _argvec[6] = (unsigned long)(arg6); \
4930 _argvec[7] = (unsigned long)(arg7); \
4931 _argvec[8] = (unsigned long)(arg8); \
4932 _argvec[9] = (unsigned long)(arg9); \
4933 _argvec[10] = (unsigned long)(arg10); \
4934 _argvec[11] = (unsigned long)(arg11); \
4935 __asm__ volatile( \
4936 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004937 "sw $28, 0($29) \n\t" \
4938 "sw $31, 4($29) \n\t" \
4939 "lw $4, 20(%1) \n\t" \
4940 "subu $29, $29, 48\n\t" \
4941 "sw $4, 16($29) \n\t" \
4942 "lw $4, 24(%1) \n\t" \
4943 "sw $4, 20($29) \n\t" \
4944 "lw $4, 28(%1) \n\t" \
4945 "sw $4, 24($29) \n\t" \
4946 "lw $4, 32(%1) \n\t" \
4947 "sw $4, 28($29) \n\t" \
4948 "lw $4, 36(%1) \n\t" \
4949 "sw $4, 32($29) \n\t" \
4950 "lw $4, 40(%1) \n\t" \
4951 "sw $4, 36($29) \n\t" \
4952 "lw $4, 44(%1) \n\t" \
4953 "sw $4, 40($29) \n\t" \
4954 "lw $4, 4(%1) \n\t" \
4955 "lw $5, 8(%1) \n\t" \
4956 "lw $6, 12(%1) \n\t" \
4957 "lw $7, 16(%1) \n\t" \
4958 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00004959 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00004960 "addu $29, $29, 48 \n\t" \
4961 "lw $28, 0($29) \n\t" \
4962 "lw $31, 4($29) \n\t" \
4963 "addu $29, $29, 8 \n\t" \
4964 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00004965 : /*out*/ "=r" (_res) \
4966 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00004967 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00004968 ); \
4969 lval = (__typeof__(lval)) _res; \
4970 } while (0)
4971
4972#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
4973 arg6,arg7,arg8,arg9,arg10, \
4974 arg11,arg12) \
4975 do { \
4976 volatile OrigFn _orig = (orig); \
4977 volatile unsigned long _argvec[13]; \
4978 volatile unsigned long _res; \
4979 _argvec[0] = (unsigned long)_orig.nraddr; \
4980 _argvec[1] = (unsigned long)(arg1); \
4981 _argvec[2] = (unsigned long)(arg2); \
4982 _argvec[3] = (unsigned long)(arg3); \
4983 _argvec[4] = (unsigned long)(arg4); \
4984 _argvec[5] = (unsigned long)(arg5); \
4985 _argvec[6] = (unsigned long)(arg6); \
4986 _argvec[7] = (unsigned long)(arg7); \
4987 _argvec[8] = (unsigned long)(arg8); \
4988 _argvec[9] = (unsigned long)(arg9); \
4989 _argvec[10] = (unsigned long)(arg10); \
4990 _argvec[11] = (unsigned long)(arg11); \
4991 _argvec[12] = (unsigned long)(arg12); \
4992 __asm__ volatile( \
4993 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00004994 "sw $28, 0($29) \n\t" \
4995 "sw $31, 4($29) \n\t" \
4996 "lw $4, 20(%1) \n\t" \
4997 "subu $29, $29, 56\n\t" \
4998 "sw $4, 16($29) \n\t" \
4999 "lw $4, 24(%1) \n\t" \
5000 "sw $4, 20($29) \n\t" \
5001 "lw $4, 28(%1) \n\t" \
5002 "sw $4, 24($29) \n\t" \
5003 "lw $4, 32(%1) \n\t" \
5004 "sw $4, 28($29) \n\t" \
5005 "lw $4, 36(%1) \n\t" \
5006 "sw $4, 32($29) \n\t" \
5007 "lw $4, 40(%1) \n\t" \
5008 "sw $4, 36($29) \n\t" \
5009 "lw $4, 44(%1) \n\t" \
5010 "sw $4, 40($29) \n\t" \
5011 "lw $4, 48(%1) \n\t" \
5012 "sw $4, 44($29) \n\t" \
5013 "lw $4, 4(%1) \n\t" \
5014 "lw $5, 8(%1) \n\t" \
5015 "lw $6, 12(%1) \n\t" \
5016 "lw $7, 16(%1) \n\t" \
5017 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005018 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00005019 "addu $29, $29, 56 \n\t" \
5020 "lw $28, 0($29) \n\t" \
5021 "lw $31, 4($29) \n\t" \
5022 "addu $29, $29, 8 \n\t" \
5023 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005024 : /*out*/ "=r" (_res) \
petarj4df0bfc2013-02-27 23:17:33 +00005025 : /*in*/ "r" (&_argvec[0]) \
5026 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005027 ); \
5028 lval = (__typeof__(lval)) _res; \
5029 } while (0)
5030
5031#endif /* PLAT_mips32_linux */
5032
petarj4df0bfc2013-02-27 23:17:33 +00005033/* ------------------------- mips64-linux ------------------------- */
5034
5035#if defined(PLAT_mips64_linux)
5036
5037/* These regs are trashed by the hidden call. */
5038#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \
5039"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
5040"$25", "$31"
5041
5042/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
5043 long) == 4. */
5044
5045#define CALL_FN_W_v(lval, orig) \
5046 do { \
5047 volatile OrigFn _orig = (orig); \
5048 volatile unsigned long _argvec[1]; \
5049 volatile unsigned long _res; \
5050 _argvec[0] = (unsigned long)_orig.nraddr; \
5051 __asm__ volatile( \
5052 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5053 VALGRIND_CALL_NOREDIR_T9 \
5054 "move %0, $2\n" \
5055 : /*out*/ "=r" (_res) \
5056 : /*in*/ "0" (&_argvec[0]) \
5057 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5058 ); \
5059 lval = (__typeof__(lval)) _res; \
5060 } while (0)
5061
5062#define CALL_FN_W_W(lval, orig, arg1) \
5063 do { \
5064 volatile OrigFn _orig = (orig); \
5065 volatile unsigned long _argvec[2]; \
5066 volatile unsigned long _res; \
5067 _argvec[0] = (unsigned long)_orig.nraddr; \
5068 _argvec[1] = (unsigned long)(arg1); \
5069 __asm__ volatile( \
5070 "ld $4, 8(%1)\n\t" /* arg1*/ \
5071 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5072 VALGRIND_CALL_NOREDIR_T9 \
5073 "move %0, $2\n" \
5074 : /*out*/ "=r" (_res) \
5075 : /*in*/ "r" (&_argvec[0]) \
5076 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5077 ); \
5078 lval = (__typeof__(lval)) _res; \
5079 } while (0)
5080
5081#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
5082 do { \
5083 volatile OrigFn _orig = (orig); \
5084 volatile unsigned long _argvec[3]; \
5085 volatile unsigned long _res; \
5086 _argvec[0] = (unsigned long)_orig.nraddr; \
5087 _argvec[1] = (unsigned long)(arg1); \
5088 _argvec[2] = (unsigned long)(arg2); \
5089 __asm__ volatile( \
5090 "ld $4, 8(%1)\n\t" \
5091 "ld $5, 16(%1)\n\t" \
5092 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5093 VALGRIND_CALL_NOREDIR_T9 \
5094 "move %0, $2\n" \
5095 : /*out*/ "=r" (_res) \
5096 : /*in*/ "r" (&_argvec[0]) \
5097 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5098 ); \
5099 lval = (__typeof__(lval)) _res; \
5100 } while (0)
5101
5102#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
5103 do { \
5104 volatile OrigFn _orig = (orig); \
5105 volatile unsigned long _argvec[4]; \
5106 volatile unsigned long _res; \
5107 _argvec[0] = (unsigned long)_orig.nraddr; \
5108 _argvec[1] = (unsigned long)(arg1); \
5109 _argvec[2] = (unsigned long)(arg2); \
5110 _argvec[3] = (unsigned long)(arg3); \
5111 __asm__ volatile( \
5112 "ld $4, 8(%1)\n\t" \
5113 "ld $5, 16(%1)\n\t" \
5114 "ld $6, 24(%1)\n\t" \
5115 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5116 VALGRIND_CALL_NOREDIR_T9 \
5117 "move %0, $2\n" \
5118 : /*out*/ "=r" (_res) \
5119 : /*in*/ "r" (&_argvec[0]) \
5120 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5121 ); \
5122 lval = (__typeof__(lval)) _res; \
5123 } while (0)
5124
5125#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
5126 do { \
5127 volatile OrigFn _orig = (orig); \
5128 volatile unsigned long _argvec[5]; \
5129 volatile unsigned long _res; \
5130 _argvec[0] = (unsigned long)_orig.nraddr; \
5131 _argvec[1] = (unsigned long)(arg1); \
5132 _argvec[2] = (unsigned long)(arg2); \
5133 _argvec[3] = (unsigned long)(arg3); \
5134 _argvec[4] = (unsigned long)(arg4); \
5135 __asm__ volatile( \
5136 "ld $4, 8(%1)\n\t" \
5137 "ld $5, 16(%1)\n\t" \
5138 "ld $6, 24(%1)\n\t" \
5139 "ld $7, 32(%1)\n\t" \
5140 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5141 VALGRIND_CALL_NOREDIR_T9 \
5142 "move %0, $2\n" \
5143 : /*out*/ "=r" (_res) \
5144 : /*in*/ "r" (&_argvec[0]) \
5145 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5146 ); \
5147 lval = (__typeof__(lval)) _res; \
5148 } while (0)
5149
5150#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
5151 do { \
5152 volatile OrigFn _orig = (orig); \
5153 volatile unsigned long _argvec[6]; \
5154 volatile unsigned long _res; \
5155 _argvec[0] = (unsigned long)_orig.nraddr; \
5156 _argvec[1] = (unsigned long)(arg1); \
5157 _argvec[2] = (unsigned long)(arg2); \
5158 _argvec[3] = (unsigned long)(arg3); \
5159 _argvec[4] = (unsigned long)(arg4); \
5160 _argvec[5] = (unsigned long)(arg5); \
5161 __asm__ volatile( \
5162 "ld $4, 8(%1)\n\t" \
5163 "ld $5, 16(%1)\n\t" \
5164 "ld $6, 24(%1)\n\t" \
5165 "ld $7, 32(%1)\n\t" \
5166 "ld $8, 40(%1)\n\t" \
5167 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5168 VALGRIND_CALL_NOREDIR_T9 \
5169 "move %0, $2\n" \
5170 : /*out*/ "=r" (_res) \
5171 : /*in*/ "r" (&_argvec[0]) \
5172 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5173 ); \
5174 lval = (__typeof__(lval)) _res; \
5175 } while (0)
5176
5177#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
5178 do { \
5179 volatile OrigFn _orig = (orig); \
5180 volatile unsigned long _argvec[7]; \
5181 volatile unsigned long _res; \
5182 _argvec[0] = (unsigned long)_orig.nraddr; \
5183 _argvec[1] = (unsigned long)(arg1); \
5184 _argvec[2] = (unsigned long)(arg2); \
5185 _argvec[3] = (unsigned long)(arg3); \
5186 _argvec[4] = (unsigned long)(arg4); \
5187 _argvec[5] = (unsigned long)(arg5); \
5188 _argvec[6] = (unsigned long)(arg6); \
5189 __asm__ volatile( \
5190 "ld $4, 8(%1)\n\t" \
5191 "ld $5, 16(%1)\n\t" \
5192 "ld $6, 24(%1)\n\t" \
5193 "ld $7, 32(%1)\n\t" \
5194 "ld $8, 40(%1)\n\t" \
5195 "ld $9, 48(%1)\n\t" \
5196 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5197 VALGRIND_CALL_NOREDIR_T9 \
5198 "move %0, $2\n" \
5199 : /*out*/ "=r" (_res) \
5200 : /*in*/ "r" (&_argvec[0]) \
5201 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5202 ); \
5203 lval = (__typeof__(lval)) _res; \
5204 } while (0)
5205
5206#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5207 arg7) \
5208 do { \
5209 volatile OrigFn _orig = (orig); \
5210 volatile unsigned long _argvec[8]; \
5211 volatile unsigned long _res; \
5212 _argvec[0] = (unsigned long)_orig.nraddr; \
5213 _argvec[1] = (unsigned long)(arg1); \
5214 _argvec[2] = (unsigned long)(arg2); \
5215 _argvec[3] = (unsigned long)(arg3); \
5216 _argvec[4] = (unsigned long)(arg4); \
5217 _argvec[5] = (unsigned long)(arg5); \
5218 _argvec[6] = (unsigned long)(arg6); \
5219 _argvec[7] = (unsigned long)(arg7); \
5220 __asm__ volatile( \
5221 "ld $4, 8(%1)\n\t" \
5222 "ld $5, 16(%1)\n\t" \
5223 "ld $6, 24(%1)\n\t" \
5224 "ld $7, 32(%1)\n\t" \
5225 "ld $8, 40(%1)\n\t" \
5226 "ld $9, 48(%1)\n\t" \
5227 "ld $10, 56(%1)\n\t" \
5228 "ld $25, 0(%1) \n\t" /* target->t9 */ \
5229 VALGRIND_CALL_NOREDIR_T9 \
5230 "move %0, $2\n" \
5231 : /*out*/ "=r" (_res) \
5232 : /*in*/ "r" (&_argvec[0]) \
5233 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5234 ); \
5235 lval = (__typeof__(lval)) _res; \
5236 } while (0)
5237
5238#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5239 arg7,arg8) \
5240 do { \
5241 volatile OrigFn _orig = (orig); \
5242 volatile unsigned long _argvec[9]; \
5243 volatile unsigned long _res; \
5244 _argvec[0] = (unsigned long)_orig.nraddr; \
5245 _argvec[1] = (unsigned long)(arg1); \
5246 _argvec[2] = (unsigned long)(arg2); \
5247 _argvec[3] = (unsigned long)(arg3); \
5248 _argvec[4] = (unsigned long)(arg4); \
5249 _argvec[5] = (unsigned long)(arg5); \
5250 _argvec[6] = (unsigned long)(arg6); \
5251 _argvec[7] = (unsigned long)(arg7); \
5252 _argvec[8] = (unsigned long)(arg8); \
5253 __asm__ volatile( \
5254 "ld $4, 8(%1)\n\t" \
5255 "ld $5, 16(%1)\n\t" \
5256 "ld $6, 24(%1)\n\t" \
5257 "ld $7, 32(%1)\n\t" \
5258 "ld $8, 40(%1)\n\t" \
5259 "ld $9, 48(%1)\n\t" \
5260 "ld $10, 56(%1)\n\t" \
5261 "ld $11, 64(%1)\n\t" \
5262 "ld $25, 0(%1) \n\t" /* target->t9 */ \
5263 VALGRIND_CALL_NOREDIR_T9 \
5264 "move %0, $2\n" \
5265 : /*out*/ "=r" (_res) \
5266 : /*in*/ "r" (&_argvec[0]) \
5267 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5268 ); \
5269 lval = (__typeof__(lval)) _res; \
5270 } while (0)
5271
5272#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5273 arg7,arg8,arg9) \
5274 do { \
5275 volatile OrigFn _orig = (orig); \
5276 volatile unsigned long _argvec[10]; \
5277 volatile unsigned long _res; \
5278 _argvec[0] = (unsigned long)_orig.nraddr; \
5279 _argvec[1] = (unsigned long)(arg1); \
5280 _argvec[2] = (unsigned long)(arg2); \
5281 _argvec[3] = (unsigned long)(arg3); \
5282 _argvec[4] = (unsigned long)(arg4); \
5283 _argvec[5] = (unsigned long)(arg5); \
5284 _argvec[6] = (unsigned long)(arg6); \
5285 _argvec[7] = (unsigned long)(arg7); \
5286 _argvec[8] = (unsigned long)(arg8); \
5287 _argvec[9] = (unsigned long)(arg9); \
5288 __asm__ volatile( \
5289 "dsubu $29, $29, 8\n\t" \
5290 "ld $4, 72(%1)\n\t" \
5291 "sd $4, 0($29)\n\t" \
5292 "ld $4, 8(%1)\n\t" \
5293 "ld $5, 16(%1)\n\t" \
5294 "ld $6, 24(%1)\n\t" \
5295 "ld $7, 32(%1)\n\t" \
5296 "ld $8, 40(%1)\n\t" \
5297 "ld $9, 48(%1)\n\t" \
5298 "ld $10, 56(%1)\n\t" \
5299 "ld $11, 64(%1)\n\t" \
5300 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5301 VALGRIND_CALL_NOREDIR_T9 \
5302 "daddu $29, $29, 8\n\t" \
5303 "move %0, $2\n" \
5304 : /*out*/ "=r" (_res) \
5305 : /*in*/ "r" (&_argvec[0]) \
5306 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5307 ); \
5308 lval = (__typeof__(lval)) _res; \
5309 } while (0)
5310
5311#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5312 arg7,arg8,arg9,arg10) \
5313 do { \
5314 volatile OrigFn _orig = (orig); \
5315 volatile unsigned long _argvec[11]; \
5316 volatile unsigned long _res; \
5317 _argvec[0] = (unsigned long)_orig.nraddr; \
5318 _argvec[1] = (unsigned long)(arg1); \
5319 _argvec[2] = (unsigned long)(arg2); \
5320 _argvec[3] = (unsigned long)(arg3); \
5321 _argvec[4] = (unsigned long)(arg4); \
5322 _argvec[5] = (unsigned long)(arg5); \
5323 _argvec[6] = (unsigned long)(arg6); \
5324 _argvec[7] = (unsigned long)(arg7); \
5325 _argvec[8] = (unsigned long)(arg8); \
5326 _argvec[9] = (unsigned long)(arg9); \
5327 _argvec[10] = (unsigned long)(arg10); \
5328 __asm__ volatile( \
5329 "dsubu $29, $29, 16\n\t" \
5330 "ld $4, 72(%1)\n\t" \
5331 "sd $4, 0($29)\n\t" \
5332 "ld $4, 80(%1)\n\t" \
5333 "sd $4, 8($29)\n\t" \
5334 "ld $4, 8(%1)\n\t" \
5335 "ld $5, 16(%1)\n\t" \
5336 "ld $6, 24(%1)\n\t" \
5337 "ld $7, 32(%1)\n\t" \
5338 "ld $8, 40(%1)\n\t" \
5339 "ld $9, 48(%1)\n\t" \
5340 "ld $10, 56(%1)\n\t" \
5341 "ld $11, 64(%1)\n\t" \
5342 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5343 VALGRIND_CALL_NOREDIR_T9 \
5344 "daddu $29, $29, 16\n\t" \
5345 "move %0, $2\n" \
5346 : /*out*/ "=r" (_res) \
5347 : /*in*/ "r" (&_argvec[0]) \
5348 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5349 ); \
5350 lval = (__typeof__(lval)) _res; \
5351 } while (0)
5352
5353#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
5354 arg6,arg7,arg8,arg9,arg10, \
5355 arg11) \
5356 do { \
5357 volatile OrigFn _orig = (orig); \
5358 volatile unsigned long _argvec[12]; \
5359 volatile unsigned long _res; \
5360 _argvec[0] = (unsigned long)_orig.nraddr; \
5361 _argvec[1] = (unsigned long)(arg1); \
5362 _argvec[2] = (unsigned long)(arg2); \
5363 _argvec[3] = (unsigned long)(arg3); \
5364 _argvec[4] = (unsigned long)(arg4); \
5365 _argvec[5] = (unsigned long)(arg5); \
5366 _argvec[6] = (unsigned long)(arg6); \
5367 _argvec[7] = (unsigned long)(arg7); \
5368 _argvec[8] = (unsigned long)(arg8); \
5369 _argvec[9] = (unsigned long)(arg9); \
5370 _argvec[10] = (unsigned long)(arg10); \
5371 _argvec[11] = (unsigned long)(arg11); \
5372 __asm__ volatile( \
5373 "dsubu $29, $29, 24\n\t" \
5374 "ld $4, 72(%1)\n\t" \
5375 "sd $4, 0($29)\n\t" \
5376 "ld $4, 80(%1)\n\t" \
5377 "sd $4, 8($29)\n\t" \
5378 "ld $4, 88(%1)\n\t" \
5379 "sd $4, 16($29)\n\t" \
5380 "ld $4, 8(%1)\n\t" \
5381 "ld $5, 16(%1)\n\t" \
5382 "ld $6, 24(%1)\n\t" \
5383 "ld $7, 32(%1)\n\t" \
5384 "ld $8, 40(%1)\n\t" \
5385 "ld $9, 48(%1)\n\t" \
5386 "ld $10, 56(%1)\n\t" \
5387 "ld $11, 64(%1)\n\t" \
5388 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5389 VALGRIND_CALL_NOREDIR_T9 \
5390 "daddu $29, $29, 24\n\t" \
5391 "move %0, $2\n" \
5392 : /*out*/ "=r" (_res) \
5393 : /*in*/ "r" (&_argvec[0]) \
5394 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5395 ); \
5396 lval = (__typeof__(lval)) _res; \
5397 } while (0)
5398
5399#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
5400 arg6,arg7,arg8,arg9,arg10, \
5401 arg11,arg12) \
5402 do { \
5403 volatile OrigFn _orig = (orig); \
5404 volatile unsigned long _argvec[13]; \
5405 volatile unsigned long _res; \
5406 _argvec[0] = (unsigned long)_orig.nraddr; \
5407 _argvec[1] = (unsigned long)(arg1); \
5408 _argvec[2] = (unsigned long)(arg2); \
5409 _argvec[3] = (unsigned long)(arg3); \
5410 _argvec[4] = (unsigned long)(arg4); \
5411 _argvec[5] = (unsigned long)(arg5); \
5412 _argvec[6] = (unsigned long)(arg6); \
5413 _argvec[7] = (unsigned long)(arg7); \
5414 _argvec[8] = (unsigned long)(arg8); \
5415 _argvec[9] = (unsigned long)(arg9); \
5416 _argvec[10] = (unsigned long)(arg10); \
5417 _argvec[11] = (unsigned long)(arg11); \
5418 _argvec[12] = (unsigned long)(arg12); \
5419 __asm__ volatile( \
5420 "dsubu $29, $29, 32\n\t" \
5421 "ld $4, 72(%1)\n\t" \
5422 "sd $4, 0($29)\n\t" \
5423 "ld $4, 80(%1)\n\t" \
5424 "sd $4, 8($29)\n\t" \
5425 "ld $4, 88(%1)\n\t" \
5426 "sd $4, 16($29)\n\t" \
5427 "ld $4, 96(%1)\n\t" \
5428 "sd $4, 24($29)\n\t" \
5429 "ld $4, 8(%1)\n\t" \
5430 "ld $5, 16(%1)\n\t" \
5431 "ld $6, 24(%1)\n\t" \
5432 "ld $7, 32(%1)\n\t" \
5433 "ld $8, 40(%1)\n\t" \
5434 "ld $9, 48(%1)\n\t" \
5435 "ld $10, 56(%1)\n\t" \
5436 "ld $11, 64(%1)\n\t" \
5437 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5438 VALGRIND_CALL_NOREDIR_T9 \
5439 "daddu $29, $29, 32\n\t" \
5440 "move %0, $2\n" \
5441 : /*out*/ "=r" (_res) \
5442 : /*in*/ "r" (&_argvec[0]) \
5443 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5444 ); \
5445 lval = (__typeof__(lval)) _res; \
5446 } while (0)
5447
5448#endif /* PLAT_mips64_linux */
5449
sewardj0ec07f32006-01-12 12:32:32 +00005450
5451/* ------------------------------------------------------------------ */
5452/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
5453/* */
njn30d76c62005-06-18 15:07:39 +00005454/* ------------------------------------------------------------------ */
5455
sewardj2e93c502002-04-12 11:12:52 +00005456/* Some request codes. There are many more of these, but most are not
5457 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00005458 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00005459
sewardj0ec07f32006-01-12 12:32:32 +00005460 Core ones are in the range 0x00000000--0x0000ffff. The non-public
5461 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00005462*/
5463
sewardj0ec07f32006-01-12 12:32:32 +00005464/* These macros are used by tools -- they must be public, but don't
5465 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00005466#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00005467 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00005468#define VG_IS_TOOL_USERREQ(a, b, v) \
5469 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00005470
sewardj5ce4b152006-03-11 12:57:41 +00005471/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
5472 This enum comprises an ABI exported by Valgrind to programs
5473 which use client requests. DO NOT CHANGE THE ORDER OF THESE
5474 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00005475typedef
njn4c791212003-05-02 17:53:54 +00005476 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
5477 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00005478
sewardj0ec07f32006-01-12 12:32:32 +00005479 /* These allow any function to be called from the simulated
5480 CPU but run on the real CPU. Nb: the first arg passed to
5481 the function is always the ThreadId of the running
5482 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00005483 function, etc. */
njn4c791212003-05-02 17:53:54 +00005484 VG_USERREQ__CLIENT_CALL0 = 0x1101,
5485 VG_USERREQ__CLIENT_CALL1 = 0x1102,
5486 VG_USERREQ__CLIENT_CALL2 = 0x1103,
5487 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00005488
sewardj0ec07f32006-01-12 12:32:32 +00005489 /* Can be useful in regression testing suites -- eg. can
5490 send Valgrind's output to /dev/null and still count
5491 errors. */
njn4c791212003-05-02 17:53:54 +00005492 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00005493
philippe46207652013-01-20 17:11:58 +00005494 /* Allows the client program and/or gdbserver to execute a monitor
5495 command. */
sewardj3b290482011-05-06 21:02:55 +00005496 VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
5497
sewardj0ec07f32006-01-12 12:32:32 +00005498 /* These are useful and can be interpreted by any tool that
5499 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00005500 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
bart91347382011-03-25 20:07:25 +00005501 VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
njnd7994182003-10-02 13:44:04 +00005502 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00005503 /* Memory pool support. */
5504 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
5505 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
5506 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
5507 VG_USERREQ__MEMPOOL_FREE = 0x1306,
sewardj2c1c9df2006-07-28 00:06:37 +00005508 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
sewardjc740d762006-10-05 17:59:23 +00005509 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
5510 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
5511 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
njnd7994182003-10-02 13:44:04 +00005512
fitzhardinge39de4b42003-10-31 07:12:21 +00005513 /* Allow printfs to valgrind log. */
sewardjc560fb32010-01-28 15:23:54 +00005514 /* The first two pass the va_list argument by value, which
5515 assumes it is the same size as or smaller than a UWord,
5516 which generally isn't the case. Hence are deprecated.
5517 The second two pass the vargs by reference and so are
5518 immune to this problem. */
5519 /* both :: char* fmt, va_list vargs (DEPRECATED) */
njn30d76c62005-06-18 15:07:39 +00005520 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00005521 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
sewardjc560fb32010-01-28 15:23:54 +00005522 /* both :: char* fmt, va_list* vargs */
5523 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
5524 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
rjwalsh0140af52005-06-04 20:42:33 +00005525
5526 /* Stack support. */
5527 VG_USERREQ__STACK_REGISTER = 0x1501,
5528 VG_USERREQ__STACK_DEREGISTER = 0x1502,
sewardjc8259b82009-04-22 22:42:10 +00005529 VG_USERREQ__STACK_CHANGE = 0x1503,
5530
5531 /* Wine support */
sewardj5c659622010-08-20 18:22:07 +00005532 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
5533
5534 /* Querying of debug info. */
sewardjdc873c02011-07-24 16:02:33 +00005535 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
5536
5537 /* Disable/enable error reporting level. Takes a single
5538 Word arg which is the delta to this thread's error
5539 disablement indicator. Hence 1 disables or further
5540 disables errors, and -1 moves back towards enablement.
5541 Other values are not allowed. */
florianbb913cd2012-08-28 16:50:39 +00005542 VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801,
5543
5544 /* Initialise IR injection */
5545 VG_USERREQ__VEX_INIT_FOR_IRI = 0x1901
njn25e49d8e72002-09-23 09:36:25 +00005546 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00005547
sewardj0ec07f32006-01-12 12:32:32 +00005548#if !defined(__GNUC__)
5549# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00005550#endif
sewardj2e93c502002-04-12 11:12:52 +00005551
bartfa5115a2010-09-02 09:33:02 +00005552
sewardj0ec07f32006-01-12 12:32:32 +00005553/* Returns the number of Valgrinds this code is running under. That
5554 is, 0 if running natively, 1 if running under Valgrind, 2 if
5555 running under Valgrind which is running under another Valgrind,
5556 etc. */
bartfa5115a2010-09-02 09:33:02 +00005557#define RUNNING_ON_VALGRIND \
bart575ce8e2011-05-15 07:04:03 +00005558 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \
bartfa5115a2010-09-02 09:33:02 +00005559 VG_USERREQ__RUNNING_ON_VALGRIND, \
5560 0, 0, 0, 0, 0) \
sewardjde4a1d02002-03-22 01:27:54 +00005561
5562
sewardj18d75132002-05-16 11:06:21 +00005563/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
5564 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
5565 since it provides a way to make sure valgrind will retranslate the
5566 invalidated area. Returns no value. */
sewardj4b3a7422011-10-24 13:21:57 +00005567#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
5568 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DISCARD_TRANSLATIONS, \
5569 _qzz_addr, _qzz_len, 0, 0, 0)
sewardj18d75132002-05-16 11:06:21 +00005570
njn26aba4d2005-05-16 13:31:23 +00005571
sewardj0ec07f32006-01-12 12:32:32 +00005572/* These requests are for getting Valgrind itself to print something.
njnd55f0d92009-08-03 01:38:56 +00005573 Possibly with a backtrace. This is a really ugly hack. The return value
5574 is the number of characters printed, excluding the "**<pid>** " part at the
5575 start and the backtrace (if present). */
sewardj0ec07f32006-01-12 12:32:32 +00005576
bart42f83fe2012-01-31 10:13:51 +00005577#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00005578/* Modern GCC will optimize the static routine out if unused,
5579 and unused attribute will shut down warnings about it. */
5580static int VALGRIND_PRINTF(const char *format, ...)
5581 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00005582#endif
sewardj7eca0cc2006-04-12 17:15:35 +00005583static int
bart0da2c772010-09-01 10:18:36 +00005584#if defined(_MSC_VER)
5585__inline
5586#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00005587VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00005588{
bart8c7e25f2011-03-04 16:55:56 +00005589#if defined(NVALGRIND)
5590 return 0;
5591#else /* NVALGRIND */
bartaaaf21d2013-08-25 06:10:24 +00005592#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00005593 uintptr_t _qzz_res;
5594#else
njnc6168192004-11-29 13:54:10 +00005595 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00005596#endif
sewardjc560fb32010-01-28 15:23:54 +00005597 va_list vargs;
5598 va_start(vargs, format);
bartaaaf21d2013-08-25 06:10:24 +00005599#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00005600 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00005601 VG_USERREQ__PRINTF_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00005602 (uintptr_t)format,
5603 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00005604 0, 0, 0);
5605#else
bart575ce8e2011-05-15 07:04:03 +00005606 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00005607 VG_USERREQ__PRINTF_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00005608 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00005609 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00005610 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00005611#endif
sewardjc560fb32010-01-28 15:23:54 +00005612 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00005613 return (int)_qzz_res;
bart8c7e25f2011-03-04 16:55:56 +00005614#endif /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00005615}
5616
bart42f83fe2012-01-31 10:13:51 +00005617#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00005618static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
5619 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00005620#endif
sewardj7eca0cc2006-04-12 17:15:35 +00005621static int
bart0da2c772010-09-01 10:18:36 +00005622#if defined(_MSC_VER)
5623__inline
5624#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00005625VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00005626{
bart8c7e25f2011-03-04 16:55:56 +00005627#if defined(NVALGRIND)
5628 return 0;
5629#else /* NVALGRIND */
bartaaaf21d2013-08-25 06:10:24 +00005630#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00005631 uintptr_t _qzz_res;
5632#else
njnc6168192004-11-29 13:54:10 +00005633 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00005634#endif
sewardjc560fb32010-01-28 15:23:54 +00005635 va_list vargs;
5636 va_start(vargs, format);
bartaaaf21d2013-08-25 06:10:24 +00005637#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00005638 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00005639 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00005640 (uintptr_t)format,
5641 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00005642 0, 0, 0);
5643#else
bart575ce8e2011-05-15 07:04:03 +00005644 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00005645 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00005646 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00005647 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00005648 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00005649#endif
sewardjc560fb32010-01-28 15:23:54 +00005650 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00005651 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00005652#endif /* NVALGRIND */
bart8c7e25f2011-03-04 16:55:56 +00005653}
sewardj18d75132002-05-16 11:06:21 +00005654
sewardj0ec07f32006-01-12 12:32:32 +00005655
njn3e884182003-04-15 13:03:23 +00005656/* These requests allow control to move from the simulated CPU to the
njn1319b492006-11-20 22:02:40 +00005657 real CPU, calling an arbitary function.
5658
5659 Note that the current ThreadId is inserted as the first argument.
5660 So this call:
5661
5662 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
5663
5664 requires f to have this signature:
5665
5666 Word f(Word tid, Word arg1, Word arg2)
5667
5668 where "Word" is a word-sized type.
njn45fb4d32007-12-05 21:51:50 +00005669
5670 Note that these client requests are not entirely reliable. For example,
5671 if you call a function with them that subsequently calls printf(),
5672 there's a high chance Valgrind will crash. Generally, your prospects of
5673 these working are made higher if the called function does not refer to
5674 any global variables, and does not refer to any libc or other functions
5675 (printf et al). Any kind of entanglement with libc or dynamic linking is
5676 likely to have a bad outcome, for tricky reasons which we've grappled
5677 with a lot in the past.
njn1319b492006-11-20 22:02:40 +00005678*/
sewardj0ec07f32006-01-12 12:32:32 +00005679#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
bart575ce8e2011-05-15 07:04:03 +00005680 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
5681 VG_USERREQ__CLIENT_CALL0, \
5682 _qyy_fn, \
5683 0, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00005684
bart575ce8e2011-05-15 07:04:03 +00005685#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
5686 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
5687 VG_USERREQ__CLIENT_CALL1, \
5688 _qyy_fn, \
5689 _qyy_arg1, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00005690
bart575ce8e2011-05-15 07:04:03 +00005691#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
5692 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
5693 VG_USERREQ__CLIENT_CALL2, \
5694 _qyy_fn, \
5695 _qyy_arg1, _qyy_arg2, 0, 0)
njn3e884182003-04-15 13:03:23 +00005696
sewardj0ec07f32006-01-12 12:32:32 +00005697#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
bart575ce8e2011-05-15 07:04:03 +00005698 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
5699 VG_USERREQ__CLIENT_CALL3, \
5700 _qyy_fn, \
5701 _qyy_arg1, _qyy_arg2, \
5702 _qyy_arg3, 0)
njn3e884182003-04-15 13:03:23 +00005703
5704
nethercote7cc9c232004-01-21 15:08:04 +00005705/* Counts the number of errors that have been recorded by a tool. Nb:
5706 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00005707 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00005708#define VALGRIND_COUNT_ERRORS \
bart575ce8e2011-05-15 07:04:03 +00005709 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR( \
5710 0 /* default return */, \
sewardj0ec07f32006-01-12 12:32:32 +00005711 VG_USERREQ__COUNT_ERRORS, \
bart575ce8e2011-05-15 07:04:03 +00005712 0, 0, 0, 0, 0)
njn47363ab2003-04-21 13:24:40 +00005713
njn3ac96952009-07-09 23:35:44 +00005714/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
5715 when heap blocks are allocated in order to give accurate results. This
5716 happens automatically for the standard allocator functions such as
5717 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
5718 delete[], etc.
njnd7994182003-10-02 13:44:04 +00005719
njn3ac96952009-07-09 23:35:44 +00005720 But if your program uses a custom allocator, this doesn't automatically
5721 happen, and Valgrind will not do as well. For example, if you allocate
5722 superblocks with mmap() and then allocates chunks of the superblocks, all
5723 Valgrind's observations will be at the mmap() level and it won't know that
5724 the chunks should be considered separate entities. In Memcheck's case,
5725 that means you probably won't get heap block overrun detection (because
5726 there won't be redzones marked as unaddressable) and you definitely won't
5727 get any leak detection.
5728
5729 The following client requests allow a custom allocator to be annotated so
5730 that it can be handled accurately by Valgrind.
5731
5732 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
5733 by a malloc()-like function. For Memcheck (an illustrative case), this
5734 does two things:
5735
5736 - It records that the block has been allocated. This means any addresses
5737 within the block mentioned in error messages will be
5738 identified as belonging to the block. It also means that if the block
5739 isn't freed it will be detected by the leak checker.
5740
5741 - It marks the block as being addressable and undefined (if 'is_zeroed' is
5742 not set), or addressable and defined (if 'is_zeroed' is set). This
5743 controls how accesses to the block by the program are handled.
5744
5745 'addr' is the start of the usable block (ie. after any
5746 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
5747 can apply redzones -- these are blocks of padding at the start and end of
5748 each block. Adding redzones is recommended as it makes it much more likely
5749 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
5750 zeroed (or filled with another predictable value), as is the case for
5751 calloc().
5752
5753 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
5754 heap block -- that will be used by the client program -- is allocated.
5755 It's best to put it at the outermost level of the allocator if possible;
5756 for example, if you have a function my_alloc() which calls
5757 internal_alloc(), and the client request is put inside internal_alloc(),
5758 stack traces relating to the heap block will contain entries for both
5759 my_alloc() and internal_alloc(), which is probably not what you want.
5760
njnb965efb2009-08-10 07:36:54 +00005761 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
5762 custom blocks from within a heap block, B, that has been allocated with
5763 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
5764 -- the custom blocks will take precedence.
5765
njn3ac96952009-07-09 23:35:44 +00005766 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
5767 Memcheck, it does two things:
5768
5769 - It records that the block has been deallocated. This assumes that the
5770 block was annotated as having been allocated via
5771 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
5772
5773 - It marks the block as being unaddressable.
5774
5775 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
5776 heap block is deallocated.
5777
bart91347382011-03-25 20:07:25 +00005778 VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For
5779 Memcheck, it does four things:
5780
5781 - It records that the size of a block has been changed. This assumes that
5782 the block was annotated as having been allocated via
5783 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
5784
5785 - If the block shrunk, it marks the freed memory as being unaddressable.
5786
5787 - If the block grew, it marks the new area as undefined and defines a red
5788 zone past the end of the new block.
5789
5790 - The V-bits of the overlap between the old and the new block are preserved.
5791
5792 VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block
5793 and before deallocation of the old block.
5794
5795 In many cases, these three client requests will not be enough to get your
njn3ac96952009-07-09 23:35:44 +00005796 allocator working well with Memcheck. More specifically, if your allocator
5797 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
5798 will be necessary to mark the memory as addressable just before the zeroing
5799 occurs, otherwise you'll get a lot of invalid write errors. For example,
5800 you'll need to do this if your allocator recycles freed blocks, but it
5801 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
5802 Alternatively, if your allocator reuses freed blocks for allocator-internal
5803 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
5804
5805 Really, what's happening is a blurring of the lines between the client
5806 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
5807 memory should be considered unaddressable to the client program, but the
5808 allocator knows more than the rest of the client program and so may be able
5809 to safely access it. Extra client requests are necessary for Valgrind to
5810 understand the distinction between the allocator and the rest of the
5811 program.
5812
njn32f8d8c2009-07-15 02:31:45 +00005813 Ignored if addr == 0.
njn3ac96952009-07-09 23:35:44 +00005814*/
sewardj4b3a7422011-10-24 13:21:57 +00005815#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
5816 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MALLOCLIKE_BLOCK, \
5817 addr, sizeB, rzB, is_zeroed, 0)
njnd7994182003-10-02 13:44:04 +00005818
njn32f8d8c2009-07-15 02:31:45 +00005819/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
5820 Ignored if addr == 0.
5821*/
sewardj4b3a7422011-10-24 13:21:57 +00005822#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \
5823 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RESIZEINPLACE_BLOCK, \
5824 addr, oldSizeB, newSizeB, rzB, 0)
bart91347382011-03-25 20:07:25 +00005825
5826/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
5827 Ignored if addr == 0.
5828*/
sewardj4b3a7422011-10-24 13:21:57 +00005829#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
5830 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREELIKE_BLOCK, \
5831 addr, rzB, 0, 0, 0)
njnd7994182003-10-02 13:44:04 +00005832
rjwalshbc0bb832004-06-19 18:12:36 +00005833/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00005834#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
sewardj4b3a7422011-10-24 13:21:57 +00005835 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \
5836 pool, rzB, is_zeroed, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00005837
5838/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00005839#define VALGRIND_DESTROY_MEMPOOL(pool) \
sewardj4b3a7422011-10-24 13:21:57 +00005840 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DESTROY_MEMPOOL, \
5841 pool, 0, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00005842
5843/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00005844#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
sewardj4b3a7422011-10-24 13:21:57 +00005845 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_ALLOC, \
5846 pool, addr, size, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00005847
5848/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00005849#define VALGRIND_MEMPOOL_FREE(pool, addr) \
sewardj4b3a7422011-10-24 13:21:57 +00005850 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_FREE, \
5851 pool, addr, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00005852
sewardj2c1c9df2006-07-28 00:06:37 +00005853/* Disassociate any pieces outside a particular range. */
5854#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
sewardj4b3a7422011-10-24 13:21:57 +00005855 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_TRIM, \
5856 pool, addr, size, 0, 0)
sewardj2c1c9df2006-07-28 00:06:37 +00005857
sewardjc740d762006-10-05 17:59:23 +00005858/* Resize and/or move a piece associated with a memory pool. */
5859#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
sewardj4b3a7422011-10-24 13:21:57 +00005860 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MOVE_MEMPOOL, \
5861 poolA, poolB, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00005862
5863/* Resize and/or move a piece associated with a memory pool. */
5864#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
sewardj4b3a7422011-10-24 13:21:57 +00005865 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_CHANGE, \
5866 pool, addrA, addrB, size, 0)
sewardjc740d762006-10-05 17:59:23 +00005867
5868/* Return 1 if a mempool exists, else 0. */
5869#define VALGRIND_MEMPOOL_EXISTS(pool) \
bart575ce8e2011-05-15 07:04:03 +00005870 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardjc740d762006-10-05 17:59:23 +00005871 VG_USERREQ__MEMPOOL_EXISTS, \
bart575ce8e2011-05-15 07:04:03 +00005872 pool, 0, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00005873
rjwalsh0140af52005-06-04 20:42:33 +00005874/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00005875#define VALGRIND_STACK_REGISTER(start, end) \
bart575ce8e2011-05-15 07:04:03 +00005876 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00005877 VG_USERREQ__STACK_REGISTER, \
bart575ce8e2011-05-15 07:04:03 +00005878 start, end, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00005879
5880/* Unmark the piece of memory associated with a stack id as being a
5881 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00005882#define VALGRIND_STACK_DEREGISTER(id) \
sewardj4b3a7422011-10-24 13:21:57 +00005883 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_DEREGISTER, \
5884 id, 0, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00005885
5886/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00005887#define VALGRIND_STACK_CHANGE(id, start, end) \
sewardj4b3a7422011-10-24 13:21:57 +00005888 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_CHANGE, \
5889 id, start, end, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00005890
sewardjc8259b82009-04-22 22:42:10 +00005891/* Load PDB debug info for Wine PE image_map. */
sewardj4b3a7422011-10-24 13:21:57 +00005892#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
5893 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LOAD_PDB_DEBUGINFO, \
5894 fd, ptr, total_size, delta, 0)
sewardjc8259b82009-04-22 22:42:10 +00005895
sewardj5c659622010-08-20 18:22:07 +00005896/* Map a code address to a source file name and line number. buf64
5897 must point to a 64-byte buffer in the caller's address space. The
5898 result will be dumped in there and is guaranteed to be zero
5899 terminated. If no info is found, the first byte is set to zero. */
5900#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \
bart575ce8e2011-05-15 07:04:03 +00005901 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj5c659622010-08-20 18:22:07 +00005902 VG_USERREQ__MAP_IP_TO_SRCLOC, \
bart575ce8e2011-05-15 07:04:03 +00005903 addr, buf64, 0, 0, 0)
sewardj5c659622010-08-20 18:22:07 +00005904
sewardjdc873c02011-07-24 16:02:33 +00005905/* Disable error reporting for this thread. Behaves in a stack like
5906 way, so you can safely call this multiple times provided that
5907 VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times
5908 to re-enable reporting. The first call of this macro disables
5909 reporting. Subsequent calls have no effect except to increase the
5910 number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable
5911 reporting. Child threads do not inherit this setting from their
5912 parents -- they are always created with reporting enabled. */
bart06e9bf02011-10-07 09:39:56 +00005913#define VALGRIND_DISABLE_ERROR_REPORTING \
sewardj4b3a7422011-10-24 13:21:57 +00005914 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
5915 1, 0, 0, 0, 0)
sewardjdc873c02011-07-24 16:02:33 +00005916
5917/* Re-enable error reporting, as per comments on
5918 VALGRIND_DISABLE_ERROR_REPORTING. */
bart06e9bf02011-10-07 09:39:56 +00005919#define VALGRIND_ENABLE_ERROR_REPORTING \
sewardj4b3a7422011-10-24 13:21:57 +00005920 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
5921 -1, 0, 0, 0, 0)
sewardj0ec07f32006-01-12 12:32:32 +00005922
philippe46207652013-01-20 17:11:58 +00005923/* Execute a monitor command from the client program.
5924 If a connection is opened with GDB, the output will be sent
5925 according to the output mode set for vgdb.
5926 If no connection is opened, output will go to the log output.
5927 Returns 1 if command not recognised, 0 otherwise. */
5928#define VALGRIND_MONITOR_COMMAND(command) \
5929 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__GDB_MONITOR_COMMAND, \
5930 command, 0, 0, 0, 0)
5931
5932
sewardjc112c8e2011-06-24 18:26:11 +00005933#undef PLAT_x86_darwin
5934#undef PLAT_amd64_darwin
5935#undef PLAT_x86_win32
bartaaaf21d2013-08-25 06:10:24 +00005936#undef PLAT_amd64_win64
sewardjf5c1a7f2006-10-17 01:32:48 +00005937#undef PLAT_x86_linux
5938#undef PLAT_amd64_linux
5939#undef PLAT_ppc32_linux
carllcae0cc22014-08-07 23:17:29 +00005940#undef PLAT_ppc64be_linux
sewardj59570ff2010-01-01 11:59:33 +00005941#undef PLAT_arm_linux
sewardjb5b87402011-03-07 16:05:35 +00005942#undef PLAT_s390x_linux
sewardj5db15402012-06-07 09:13:21 +00005943#undef PLAT_mips32_linux
petarj4df0bfc2013-02-27 23:17:33 +00005944#undef PLAT_mips64_linux
sewardj0ec07f32006-01-12 12:32:32 +00005945
njn3e884182003-04-15 13:03:23 +00005946#endif /* __VALGRIND_H */