blob: b55924a285a7deda3c3dfdad06eb677e0e852006 [file] [log] [blame]
sewardjb5f6f512005-03-10 23:59:00 +00001/* -*- c -*-
njn25e49d8e72002-09-23 09:36:25 +00002 ----------------------------------------------------------------
3
4 Notice that the following BSD-style license applies to this one
njn7fd15d62006-03-31 12:05:04 +00005 file (valgrind.h) only. The rest of Valgrind is licensed under the
6 terms of the GNU General Public License, version 2, unless
7 otherwise indicated. See the COPYING file in the source
8 distribution for details.
njn25e49d8e72002-09-23 09:36:25 +00009
10 ----------------------------------------------------------------
11
njnb9c427c2004-12-01 14:14:42 +000012 This file is part of Valgrind, a dynamic binary instrumentation
13 framework.
sewardjde4a1d02002-03-22 01:27:54 +000014
sewardj0f157dd2013-10-18 14:27:36 +000015 Copyright (C) 2000-2013 Julian Seward. All rights reserved.
sewardjde4a1d02002-03-22 01:27:54 +000016
njn25e49d8e72002-09-23 09:36:25 +000017 Redistribution and use in source and binary forms, with or without
18 modification, are permitted provided that the following conditions
19 are met:
sewardjde4a1d02002-03-22 01:27:54 +000020
njn25e49d8e72002-09-23 09:36:25 +000021 1. Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
sewardjde4a1d02002-03-22 01:27:54 +000023
njn25e49d8e72002-09-23 09:36:25 +000024 2. The origin of this software must not be misrepresented; you must
25 not claim that you wrote the original software. If you use this
26 software in a product, an acknowledgment in the product
27 documentation would be appreciated but is not required.
sewardjde4a1d02002-03-22 01:27:54 +000028
njn25e49d8e72002-09-23 09:36:25 +000029 3. Altered source versions must be plainly marked as such, and must
30 not be misrepresented as being the original software.
31
32 4. The name of the author may not be used to endorse or promote
33 products derived from this software without specific prior written
34 permission.
35
36 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
37 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
40 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
45 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47
48 ----------------------------------------------------------------
49
50 Notice that the above BSD-style license applies to this one file
51 (valgrind.h) only. The entire rest of Valgrind is licensed under
52 the terms of the GNU General Public License, version 2. See the
53 COPYING file in the source distribution for details.
54
55 ----------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +000056*/
57
58
njn30d76c62005-06-18 15:07:39 +000059/* This file is for inclusion into client (your!) code.
60
61 You can use these macros to manipulate and query Valgrind's
62 execution inside your own programs.
63
64 The resulting executables will still run without Valgrind, just a
65 little bit more slowly than they otherwise would, but otherwise
66 unchanged. When not running on valgrind, each client request
sewardj0ec07f32006-01-12 12:32:32 +000067 consumes very few (eg. 7) instructions, so the resulting performance
njn30d76c62005-06-18 15:07:39 +000068 loss is negligible unless you plan to execute client requests
69 millions of times per second. Nevertheless, if that is still a
70 problem, you can compile with the NVALGRIND symbol defined (gcc
71 -DNVALGRIND) so that client requests are not even compiled in. */
72
sewardjde4a1d02002-03-22 01:27:54 +000073#ifndef __VALGRIND_H
74#define __VALGRIND_H
75
sewardj71044162010-03-03 22:57:47 +000076
77/* ------------------------------------------------------------------ */
78/* VERSION NUMBER OF VALGRIND */
79/* ------------------------------------------------------------------ */
80
81/* Specify Valgrind's version number, so that user code can
sewardj0fe1d4c2010-04-19 08:43:26 +000082 conditionally compile based on our version number. Note that these
83 were introduced at version 3.6 and so do not exist in version 3.5
84 or earlier. The recommended way to use them to check for "version
85 X.Y or later" is (eg)
86
87#if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \
88 && (__VALGRIND_MAJOR__ > 3 \
89 || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6))
90*/
91#define __VALGRIND_MAJOR__ 3
sewardjbd830b42014-05-12 10:12:08 +000092#define __VALGRIND_MINOR__ 10
sewardj71044162010-03-03 22:57:47 +000093
94
fitzhardinge39de4b42003-10-31 07:12:21 +000095#include <stdarg.h>
96
njn3dd0a912005-06-28 19:44:10 +000097/* Nb: this file might be included in a file compiled with -ansi. So
98 we can't use C++ style "//" comments nor the "asm" keyword (instead
99 use "__asm__"). */
100
sewardjf5c1a7f2006-10-17 01:32:48 +0000101/* Derive some tags indicating what the target platform is. Note
sewardj0ec07f32006-01-12 12:32:32 +0000102 that in this file we're using the compiler's CPP symbols for
103 identifying architectures, which are different to the ones we use
104 within the rest of Valgrind. Note, __powerpc__ is active for both
105 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
sewardj59570ff2010-01-01 11:59:33 +0000106 latter (on Linux, that is).
107
108 Misc note: how to find out what's predefined in gcc by default:
109 gcc -Wp,-dM somefile.c
110*/
sewardj7af32302010-01-02 10:37:58 +0000111#undef PLAT_x86_darwin
112#undef PLAT_amd64_darwin
bart7f489812010-08-27 10:05:27 +0000113#undef PLAT_x86_win32
bartaaaf21d2013-08-25 06:10:24 +0000114#undef PLAT_amd64_win64
sewardjf5c1a7f2006-10-17 01:32:48 +0000115#undef PLAT_x86_linux
116#undef PLAT_amd64_linux
117#undef PLAT_ppc32_linux
carllcae0cc22014-08-07 23:17:29 +0000118#undef PLAT_ppc64be_linux
carll582d5822014-08-07 23:35:54 +0000119#undef PLAT_ppc64le_linux
sewardj59570ff2010-01-01 11:59:33 +0000120#undef PLAT_arm_linux
sewardjf0c12502014-01-12 12:54:00 +0000121#undef PLAT_arm64_linux
sewardjb5b87402011-03-07 16:05:35 +0000122#undef PLAT_s390x_linux
sewardj5db15402012-06-07 09:13:21 +0000123#undef PLAT_mips32_linux
petarj4df0bfc2013-02-27 23:17:33 +0000124#undef PLAT_mips64_linux
sewardj112711a2015-04-10 12:30:09 +0000125#undef PLAT_tilegx_linux
sewardj8eb8bab2015-07-21 14:44:28 +0000126#undef PLAT_x86_solaris
127#undef PLAT_amd64_solaris
sewardjb5b87402011-03-07 16:05:35 +0000128
sewardj0ec07f32006-01-12 12:32:32 +0000129
sewardj6e9de462011-06-28 07:25:29 +0000130#if defined(__APPLE__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000131# define PLAT_x86_darwin 1
132#elif defined(__APPLE__) && defined(__x86_64__)
133# define PLAT_amd64_darwin 1
sewardjc913c8e2014-05-15 13:50:47 +0000134#elif (defined(__MINGW32__) && !defined(__MINGW64__)) \
135 || defined(__CYGWIN32__) \
sewardj6e9de462011-06-28 07:25:29 +0000136 || (defined(_WIN32) && defined(_M_IX86))
bart7f489812010-08-27 10:05:27 +0000137# define PLAT_x86_win32 1
sewardjc913c8e2014-05-15 13:50:47 +0000138#elif defined(__MINGW64__) \
139 || (defined(_WIN64) && defined(_M_X64))
bartaaaf21d2013-08-25 06:10:24 +0000140# define PLAT_amd64_win64 1
sewardj59570ff2010-01-01 11:59:33 +0000141#elif defined(__linux__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000142# define PLAT_x86_linux 1
bartf1c8e6c2015-08-12 13:29:10 +0000143#elif defined(__linux__) && defined(__x86_64__) && !defined(__ILP32__)
njnf76d27a2009-05-28 01:53:07 +0000144# define PLAT_amd64_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000145#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000146# define PLAT_ppc32_linux 1
carllcae0cc22014-08-07 23:17:29 +0000147#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF != 2
148/* Big Endian uses ELF version 1 */
149# define PLAT_ppc64be_linux 1
carll582d5822014-08-07 23:35:54 +0000150#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF == 2
151/* Little Endian uses ELF version 2 */
152# define PLAT_ppc64le_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000153#elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__)
sewardj59570ff2010-01-01 11:59:33 +0000154# define PLAT_arm_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000155#elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__)
156# define PLAT_arm64_linux 1
sewardjb5b87402011-03-07 16:05:35 +0000157#elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
158# define PLAT_s390x_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000159#elif defined(__linux__) && defined(__mips__) && (__mips==64)
petarj4df0bfc2013-02-27 23:17:33 +0000160# define PLAT_mips64_linux 1
sewardjf0c12502014-01-12 12:54:00 +0000161#elif defined(__linux__) && defined(__mips__) && (__mips!=64)
sewardj5db15402012-06-07 09:13:21 +0000162# define PLAT_mips32_linux 1
sewardj112711a2015-04-10 12:30:09 +0000163#elif defined(__linux__) && defined(__tilegx__)
164# define PLAT_tilegx_linux 1
sewardj8eb8bab2015-07-21 14:44:28 +0000165#elif defined(__sun) && defined(__i386__)
166# define PLAT_x86_solaris 1
167#elif defined(__sun) && defined(__x86_64__)
168# define PLAT_amd64_solaris 1
njnf76d27a2009-05-28 01:53:07 +0000169#else
sewardjf5c1a7f2006-10-17 01:32:48 +0000170/* If we're not compiling for our target platform, don't generate
sewardj0ec07f32006-01-12 12:32:32 +0000171 any inline asms. */
sewardj0ec07f32006-01-12 12:32:32 +0000172# if !defined(NVALGRIND)
173# define NVALGRIND 1
174# endif
175#endif
176
177
njn30d76c62005-06-18 15:07:39 +0000178/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000179/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
180/* in here of use to end-users -- skip to the next section. */
njn30d76c62005-06-18 15:07:39 +0000181/* ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000182
bart575ce8e2011-05-15 07:04:03 +0000183/*
184 * VALGRIND_DO_CLIENT_REQUEST(): a statement that invokes a Valgrind client
185 * request. Accepts both pointers and integers as arguments.
186 *
sewardj4b3a7422011-10-24 13:21:57 +0000187 * VALGRIND_DO_CLIENT_REQUEST_STMT(): a statement that invokes a Valgrind
188 * client request that does not return a value.
189
bart575ce8e2011-05-15 07:04:03 +0000190 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
sewardj4b3a7422011-10-24 13:21:57 +0000191 * client request and whose value equals the client request result. Accepts
192 * both pointers and integers as arguments. Note that such calls are not
193 * necessarily pure functions -- they may have side effects.
bart575ce8e2011-05-15 07:04:03 +0000194 */
195
196#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, \
197 _zzq_request, _zzq_arg1, _zzq_arg2, \
198 _zzq_arg3, _zzq_arg4, _zzq_arg5) \
florian17dfe1a2011-10-22 15:04:05 +0000199 do { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default), \
bart575ce8e2011-05-15 07:04:03 +0000200 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
florian17dfe1a2011-10-22 15:04:05 +0000201 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
bart575ce8e2011-05-15 07:04:03 +0000202
sewardj4b3a7422011-10-24 13:21:57 +0000203#define VALGRIND_DO_CLIENT_REQUEST_STMT(_zzq_request, _zzq_arg1, \
204 _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
205 do { (void) VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
206 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
207 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
208
sewardj0ec07f32006-01-12 12:32:32 +0000209#if defined(NVALGRIND)
njn26aba4d2005-05-16 13:31:23 +0000210
211/* Define NVALGRIND to completely remove the Valgrind magic sequence
sewardj0ec07f32006-01-12 12:32:32 +0000212 from the compiled code (analogous to NDEBUG's effects on
213 assert()) */
bart575ce8e2011-05-15 07:04:03 +0000214#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
215 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000216 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000217 (_zzq_default)
njn26aba4d2005-05-16 13:31:23 +0000218
sewardj0ec07f32006-01-12 12:32:32 +0000219#else /* ! NVALGRIND */
nethercotee90c6832004-10-18 18:07:49 +0000220
sewardj0ec07f32006-01-12 12:32:32 +0000221/* The following defines the magic code sequences which the JITter
222 spots and handles magically. Don't look too closely at them as
223 they will rot your brain.
224
225 The assembly code sequences for all architectures is in this one
226 file. This is because this file must be stand-alone, and we don't
227 want to have multiple files.
228
229 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
230 value gets put in the return slot, so that everything works when
231 this is executed not under Valgrind. Args are passed in a memory
232 block, and so there's no intrinsic limit to the number that could
sewardj9af10a12006-02-01 14:59:42 +0000233 be passed, but it's currently five.
nethercotee90c6832004-10-18 18:07:49 +0000234
nethercote54265442004-10-26 12:56:58 +0000235 The macro args are:
236 _zzq_rlval result lvalue
237 _zzq_default default value (result returned when running on real CPU)
238 _zzq_request request code
sewardj9af10a12006-02-01 14:59:42 +0000239 _zzq_arg1..5 request params
nethercote54265442004-10-26 12:56:58 +0000240
sewardj0ec07f32006-01-12 12:32:32 +0000241 The other two macros are used to support function wrapping, and are
sewardjd68ac3e2006-01-20 14:31:57 +0000242 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
243 guest's NRADDR pseudo-register and whatever other information is
244 needed to safely run the call original from the wrapper: on
245 ppc64-linux, the R2 value at the divert point is also needed. This
246 information is abstracted into a user-visible type, OrigFn.
247
248 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
249 guest, but guarantees that the branch instruction will not be
250 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
251 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
252 complete inline asm, since it needs to be combined with more magic
253 inline asm stuff to be useful.
nethercotee90c6832004-10-18 18:07:49 +0000254*/
255
sewardj8eb8bab2015-07-21 14:44:28 +0000256/* ----------------- x86-{linux,darwin,solaris} ---------------- */
sewardjde4a4ab2005-03-23 13:10:32 +0000257
sewardj520a03a2010-10-07 10:46:15 +0000258#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
sewardj8eb8bab2015-07-21 14:44:28 +0000259 || (defined(PLAT_x86_win32) && defined(__GNUC__)) \
260 || defined(PLAT_x86_solaris)
sewardjc8858442006-01-20 15:17:20 +0000261
262typedef
263 struct {
264 unsigned int nraddr; /* where's the code? */
265 }
266 OrigFn;
267
sewardj0ec07f32006-01-12 12:32:32 +0000268#define __SPECIAL_INSTRUCTION_PREAMBLE \
269 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000270 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000271
bart575ce8e2011-05-15 07:04:03 +0000272#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
273 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000274 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000275 __extension__ \
276 ({volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000277 volatile unsigned int _zzq_result; \
278 _zzq_args[0] = (unsigned int)(_zzq_request); \
279 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
280 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
281 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
282 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000283 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000284 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
285 /* %EDX = client_request ( %EAX ) */ \
286 "xchgl %%ebx,%%ebx" \
287 : "=d" (_zzq_result) \
288 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
289 : "cc", "memory" \
290 ); \
bart575ce8e2011-05-15 07:04:03 +0000291 _zzq_result; \
292 })
sewardj2c48c7b2005-11-29 13:05:56 +0000293
sewardjc8858442006-01-20 15:17:20 +0000294#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
295 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
296 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000297 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
298 /* %EAX = guest_NRADDR */ \
299 "xchgl %%ecx,%%ecx" \
300 : "=a" (__addr) \
301 : \
302 : "cc", "memory" \
303 ); \
sewardjc8858442006-01-20 15:17:20 +0000304 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000305 }
sewardj0ec07f32006-01-12 12:32:32 +0000306
307#define VALGRIND_CALL_NOREDIR_EAX \
308 __SPECIAL_INSTRUCTION_PREAMBLE \
309 /* call-noredir *%EAX */ \
310 "xchgl %%edx,%%edx\n\t"
florianbb913cd2012-08-28 16:50:39 +0000311
312#define VALGRIND_VEX_INJECT_IR() \
313 do { \
314 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
315 "xchgl %%edi,%%edi\n\t" \
316 : : : "cc", "memory" \
317 ); \
318 } while (0)
319
sewardj8eb8bab2015-07-21 14:44:28 +0000320#endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__)
321 || PLAT_x86_solaris */
bart7f489812010-08-27 10:05:27 +0000322
323/* ------------------------- x86-Win32 ------------------------- */
324
325#if defined(PLAT_x86_win32) && !defined(__GNUC__)
326
327typedef
328 struct {
329 unsigned int nraddr; /* where's the code? */
330 }
331 OrigFn;
332
333#if defined(_MSC_VER)
334
335#define __SPECIAL_INSTRUCTION_PREAMBLE \
336 __asm rol edi, 3 __asm rol edi, 13 \
337 __asm rol edi, 29 __asm rol edi, 19
338
bart575ce8e2011-05-15 07:04:03 +0000339#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
340 _zzq_default, _zzq_request, \
bart7f489812010-08-27 10:05:27 +0000341 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000342 valgrind_do_client_request_expr((uintptr_t)(_zzq_default), \
343 (uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1), \
344 (uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3), \
345 (uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5))
346
347static __inline uintptr_t
348valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request,
349 uintptr_t _zzq_arg1, uintptr_t _zzq_arg2,
350 uintptr_t _zzq_arg3, uintptr_t _zzq_arg4,
351 uintptr_t _zzq_arg5)
352{
353 volatile uintptr_t _zzq_args[6];
354 volatile unsigned int _zzq_result;
355 _zzq_args[0] = (uintptr_t)(_zzq_request);
356 _zzq_args[1] = (uintptr_t)(_zzq_arg1);
357 _zzq_args[2] = (uintptr_t)(_zzq_arg2);
358 _zzq_args[3] = (uintptr_t)(_zzq_arg3);
359 _zzq_args[4] = (uintptr_t)(_zzq_arg4);
360 _zzq_args[5] = (uintptr_t)(_zzq_arg5);
361 __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default
362 __SPECIAL_INSTRUCTION_PREAMBLE
363 /* %EDX = client_request ( %EAX ) */
364 __asm xchg ebx,ebx
365 __asm mov _zzq_result, edx
366 }
367 return _zzq_result;
368}
bart7f489812010-08-27 10:05:27 +0000369
370#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
371 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
372 volatile unsigned int __addr; \
373 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
374 /* %EAX = guest_NRADDR */ \
375 __asm xchg ecx,ecx \
376 __asm mov __addr, eax \
377 } \
378 _zzq_orig->nraddr = __addr; \
379 }
380
381#define VALGRIND_CALL_NOREDIR_EAX ERROR
382
florianbb913cd2012-08-28 16:50:39 +0000383#define VALGRIND_VEX_INJECT_IR() \
384 do { \
385 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
386 __asm xchg edi,edi \
387 } \
388 } while (0)
389
bart7f489812010-08-27 10:05:27 +0000390#else
391#error Unsupported compiler.
392#endif
393
394#endif /* PLAT_x86_win32 */
sewardj0ec07f32006-01-12 12:32:32 +0000395
sewardj8eb8bab2015-07-21 14:44:28 +0000396/* ----------------- amd64-{linux,darwin,solaris} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000397
sewardjc913c8e2014-05-15 13:50:47 +0000398#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \
sewardj8eb8bab2015-07-21 14:44:28 +0000399 || defined(PLAT_amd64_solaris) \
sewardjc913c8e2014-05-15 13:50:47 +0000400 || (defined(PLAT_amd64_win64) && defined(__GNUC__))
sewardjc8858442006-01-20 15:17:20 +0000401
402typedef
403 struct {
florian3540ee82014-11-19 07:41:19 +0000404 unsigned long int nraddr; /* where's the code? */
sewardjc8858442006-01-20 15:17:20 +0000405 }
406 OrigFn;
407
sewardj0ec07f32006-01-12 12:32:32 +0000408#define __SPECIAL_INSTRUCTION_PREAMBLE \
409 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000410 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000411
bart575ce8e2011-05-15 07:04:03 +0000412#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
413 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000414 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000415 __extension__ \
florian3540ee82014-11-19 07:41:19 +0000416 ({ volatile unsigned long int _zzq_args[6]; \
417 volatile unsigned long int _zzq_result; \
418 _zzq_args[0] = (unsigned long int)(_zzq_request); \
419 _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
420 _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
421 _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
422 _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
423 _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000424 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
425 /* %RDX = client_request ( %RAX ) */ \
426 "xchgq %%rbx,%%rbx" \
427 : "=d" (_zzq_result) \
428 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
429 : "cc", "memory" \
430 ); \
bart575ce8e2011-05-15 07:04:03 +0000431 _zzq_result; \
432 })
sewardj0ec07f32006-01-12 12:32:32 +0000433
sewardjc8858442006-01-20 15:17:20 +0000434#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
435 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
florian3540ee82014-11-19 07:41:19 +0000436 volatile unsigned long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000437 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
438 /* %RAX = guest_NRADDR */ \
439 "xchgq %%rcx,%%rcx" \
440 : "=a" (__addr) \
441 : \
442 : "cc", "memory" \
443 ); \
sewardjc8858442006-01-20 15:17:20 +0000444 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000445 }
446
447#define VALGRIND_CALL_NOREDIR_RAX \
448 __SPECIAL_INSTRUCTION_PREAMBLE \
449 /* call-noredir *%RAX */ \
450 "xchgq %%rdx,%%rdx\n\t"
florianbb913cd2012-08-28 16:50:39 +0000451
452#define VALGRIND_VEX_INJECT_IR() \
453 do { \
454 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
455 "xchgq %%rdi,%%rdi\n\t" \
456 : : : "cc", "memory" \
457 ); \
458 } while (0)
459
sewardj8eb8bab2015-07-21 14:44:28 +0000460#endif /* PLAT_amd64_linux || PLAT_amd64_darwin || PLAT_amd64_solaris */
sewardj0ec07f32006-01-12 12:32:32 +0000461
sewardjc913c8e2014-05-15 13:50:47 +0000462/* ------------------------- amd64-Win64 ------------------------- */
463
464#if defined(PLAT_amd64_win64) && !defined(__GNUC__)
465
466#error Unsupported compiler.
467
468#endif /* PLAT_amd64_win64 */
469
sewardjf5c1a7f2006-10-17 01:32:48 +0000470/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000471
sewardjf5c1a7f2006-10-17 01:32:48 +0000472#if defined(PLAT_ppc32_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000473
474typedef
475 struct {
sewardjc8858442006-01-20 15:17:20 +0000476 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000477 }
478 OrigFn;
479
sewardj0ec07f32006-01-12 12:32:32 +0000480#define __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj4decb262014-02-10 12:26:12 +0000481 "rlwinm 0,0,3,0,31 ; rlwinm 0,0,13,0,31\n\t" \
482 "rlwinm 0,0,29,0,31 ; rlwinm 0,0,19,0,31\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000483
bart575ce8e2011-05-15 07:04:03 +0000484#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
485 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000486 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000487 \
bart575ce8e2011-05-15 07:04:03 +0000488 __extension__ \
489 ({ unsigned int _zzq_args[6]; \
sewardj1c5bcb12006-12-08 21:29:46 +0000490 unsigned int _zzq_result; \
491 unsigned int* _zzq_ptr; \
sewardj0ec07f32006-01-12 12:32:32 +0000492 _zzq_args[0] = (unsigned int)(_zzq_request); \
493 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
494 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
495 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
496 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000497 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000498 _zzq_ptr = _zzq_args; \
sewardj1c5bcb12006-12-08 21:29:46 +0000499 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
500 "mr 4,%2\n\t" /*ptr*/ \
501 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj0ec07f32006-01-12 12:32:32 +0000502 /* %R3 = client_request ( %R4 ) */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000503 "or 1,1,1\n\t" \
504 "mr %0,3" /*result*/ \
505 : "=b" (_zzq_result) \
506 : "b" (_zzq_default), "b" (_zzq_ptr) \
507 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000508 _zzq_result; \
509 })
sewardj0ec07f32006-01-12 12:32:32 +0000510
sewardjd68ac3e2006-01-20 14:31:57 +0000511#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
512 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj1c5bcb12006-12-08 21:29:46 +0000513 unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000514 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
515 /* %R3 = guest_NRADDR */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000516 "or 2,2,2\n\t" \
517 "mr %0,3" \
518 : "=b" (__addr) \
sewardj0ec07f32006-01-12 12:32:32 +0000519 : \
sewardj1c5bcb12006-12-08 21:29:46 +0000520 : "cc", "memory", "r3" \
sewardj0ec07f32006-01-12 12:32:32 +0000521 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000522 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000523 }
524
525#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
526 __SPECIAL_INSTRUCTION_PREAMBLE \
527 /* branch-and-link-to-noredir *%R11 */ \
528 "or 3,3,3\n\t"
florian4d261bb2012-08-29 14:59:13 +0000529
530#define VALGRIND_VEX_INJECT_IR() \
531 do { \
532 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
533 "or 5,5,5\n\t" \
534 ); \
535 } while (0)
536
sewardjf5c1a7f2006-10-17 01:32:48 +0000537#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000538
sewardjf5c1a7f2006-10-17 01:32:48 +0000539/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000540
carllcae0cc22014-08-07 23:17:29 +0000541#if defined(PLAT_ppc64be_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000542
543typedef
544 struct {
florian3540ee82014-11-19 07:41:19 +0000545 unsigned long int nraddr; /* where's the code? */
546 unsigned long int r2; /* what tocptr do we need? */
sewardjd68ac3e2006-01-20 14:31:57 +0000547 }
548 OrigFn;
549
sewardj1a85f4f2006-01-12 21:15:35 +0000550#define __SPECIAL_INSTRUCTION_PREAMBLE \
551 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
552 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
553
bart575ce8e2011-05-15 07:04:03 +0000554#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
555 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000556 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000557 \
bart575ce8e2011-05-15 07:04:03 +0000558 __extension__ \
florian3540ee82014-11-19 07:41:19 +0000559 ({ unsigned long int _zzq_args[6]; \
560 unsigned long int _zzq_result; \
561 unsigned long int* _zzq_ptr; \
562 _zzq_args[0] = (unsigned long int)(_zzq_request); \
563 _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
564 _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
565 _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
566 _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
567 _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000568 _zzq_ptr = _zzq_args; \
sewardj8258a3a2011-10-05 07:39:07 +0000569 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
570 "mr 4,%2\n\t" /*ptr*/ \
571 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj1a85f4f2006-01-12 21:15:35 +0000572 /* %R3 = client_request ( %R4 ) */ \
sewardj8258a3a2011-10-05 07:39:07 +0000573 "or 1,1,1\n\t" \
574 "mr %0,3" /*result*/ \
575 : "=b" (_zzq_result) \
576 : "b" (_zzq_default), "b" (_zzq_ptr) \
577 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000578 _zzq_result; \
579 })
sewardj1a85f4f2006-01-12 21:15:35 +0000580
sewardjd68ac3e2006-01-20 14:31:57 +0000581#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
582 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
florian3540ee82014-11-19 07:41:19 +0000583 unsigned long int __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000584 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
585 /* %R3 = guest_NRADDR */ \
sewardj8258a3a2011-10-05 07:39:07 +0000586 "or 2,2,2\n\t" \
587 "mr %0,3" \
588 : "=b" (__addr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000589 : \
sewardj8258a3a2011-10-05 07:39:07 +0000590 : "cc", "memory", "r3" \
sewardj1a85f4f2006-01-12 21:15:35 +0000591 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000592 _zzq_orig->nraddr = __addr; \
593 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
594 /* %R3 = guest_NRADDR_GPR2 */ \
sewardj8258a3a2011-10-05 07:39:07 +0000595 "or 4,4,4\n\t" \
596 "mr %0,3" \
597 : "=b" (__addr) \
sewardjd68ac3e2006-01-20 14:31:57 +0000598 : \
sewardj8258a3a2011-10-05 07:39:07 +0000599 : "cc", "memory", "r3" \
sewardjd68ac3e2006-01-20 14:31:57 +0000600 ); \
601 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000602 }
603
604#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
605 __SPECIAL_INSTRUCTION_PREAMBLE \
606 /* branch-and-link-to-noredir *%R11 */ \
607 "or 3,3,3\n\t"
608
florianbb913cd2012-08-28 16:50:39 +0000609#define VALGRIND_VEX_INJECT_IR() \
610 do { \
611 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
612 "or 5,5,5\n\t" \
613 ); \
614 } while (0)
615
carllcae0cc22014-08-07 23:17:29 +0000616#endif /* PLAT_ppc64be_linux */
617
carll582d5822014-08-07 23:35:54 +0000618#if defined(PLAT_ppc64le_linux)
619
620typedef
621 struct {
florian3540ee82014-11-19 07:41:19 +0000622 unsigned long int nraddr; /* where's the code? */
623 unsigned long int r2; /* what tocptr do we need? */
carll582d5822014-08-07 23:35:54 +0000624 }
625 OrigFn;
626
627#define __SPECIAL_INSTRUCTION_PREAMBLE \
628 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
629 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
630
631#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
632 _zzq_default, _zzq_request, \
633 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
634 \
635 __extension__ \
florian3540ee82014-11-19 07:41:19 +0000636 ({ unsigned long int _zzq_args[6]; \
637 unsigned long int _zzq_result; \
638 unsigned long int* _zzq_ptr; \
639 _zzq_args[0] = (unsigned long int)(_zzq_request); \
640 _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
641 _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
642 _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
643 _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
644 _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
carll582d5822014-08-07 23:35:54 +0000645 _zzq_ptr = _zzq_args; \
646 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
647 "mr 4,%2\n\t" /*ptr*/ \
648 __SPECIAL_INSTRUCTION_PREAMBLE \
649 /* %R3 = client_request ( %R4 ) */ \
650 "or 1,1,1\n\t" \
651 "mr %0,3" /*result*/ \
652 : "=b" (_zzq_result) \
653 : "b" (_zzq_default), "b" (_zzq_ptr) \
654 : "cc", "memory", "r3", "r4"); \
655 _zzq_result; \
656 })
657
658#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
659 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
florian3540ee82014-11-19 07:41:19 +0000660 unsigned long int __addr; \
carll582d5822014-08-07 23:35:54 +0000661 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
662 /* %R3 = guest_NRADDR */ \
663 "or 2,2,2\n\t" \
664 "mr %0,3" \
665 : "=b" (__addr) \
666 : \
667 : "cc", "memory", "r3" \
668 ); \
669 _zzq_orig->nraddr = __addr; \
670 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
671 /* %R3 = guest_NRADDR_GPR2 */ \
672 "or 4,4,4\n\t" \
673 "mr %0,3" \
674 : "=b" (__addr) \
675 : \
676 : "cc", "memory", "r3" \
677 ); \
678 _zzq_orig->r2 = __addr; \
679 }
680
681#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
682 __SPECIAL_INSTRUCTION_PREAMBLE \
683 /* branch-and-link-to-noredir *%R12 */ \
684 "or 3,3,3\n\t"
685
686#define VALGRIND_VEX_INJECT_IR() \
687 do { \
688 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
689 "or 5,5,5\n\t" \
690 ); \
691 } while (0)
692
693#endif /* PLAT_ppc64le_linux */
cerion85665ca2005-06-20 15:51:07 +0000694
sewardj59570ff2010-01-01 11:59:33 +0000695/* ------------------------- arm-linux ------------------------- */
696
697#if defined(PLAT_arm_linux)
698
699typedef
700 struct {
701 unsigned int nraddr; /* where's the code? */
702 }
703 OrigFn;
704
705#define __SPECIAL_INSTRUCTION_PREAMBLE \
706 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
707 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
708
bart575ce8e2011-05-15 07:04:03 +0000709#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
710 _zzq_default, _zzq_request, \
sewardj59570ff2010-01-01 11:59:33 +0000711 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
712 \
bart575ce8e2011-05-15 07:04:03 +0000713 __extension__ \
714 ({volatile unsigned int _zzq_args[6]; \
sewardj59570ff2010-01-01 11:59:33 +0000715 volatile unsigned int _zzq_result; \
716 _zzq_args[0] = (unsigned int)(_zzq_request); \
717 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
718 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
719 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
720 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
721 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
722 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
723 "mov r4, %2\n\t" /*ptr*/ \
724 __SPECIAL_INSTRUCTION_PREAMBLE \
725 /* R3 = client_request ( R4 ) */ \
726 "orr r10, r10, r10\n\t" \
727 "mov %0, r3" /*result*/ \
728 : "=r" (_zzq_result) \
729 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
730 : "cc","memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000731 _zzq_result; \
732 })
sewardj59570ff2010-01-01 11:59:33 +0000733
734#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
735 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
736 unsigned int __addr; \
737 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
738 /* R3 = guest_NRADDR */ \
739 "orr r11, r11, r11\n\t" \
740 "mov %0, r3" \
741 : "=r" (__addr) \
742 : \
743 : "cc", "memory", "r3" \
744 ); \
745 _zzq_orig->nraddr = __addr; \
746 }
747
748#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
749 __SPECIAL_INSTRUCTION_PREAMBLE \
750 /* branch-and-link-to-noredir *%R4 */ \
751 "orr r12, r12, r12\n\t"
752
florianbb913cd2012-08-28 16:50:39 +0000753#define VALGRIND_VEX_INJECT_IR() \
754 do { \
755 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
sewardjc379fec2012-09-03 21:51:02 +0000756 "orr r9, r9, r9\n\t" \
florianbb913cd2012-08-28 16:50:39 +0000757 : : : "cc", "memory" \
758 ); \
759 } while (0)
760
sewardj59570ff2010-01-01 11:59:33 +0000761#endif /* PLAT_arm_linux */
762
sewardjf0c12502014-01-12 12:54:00 +0000763/* ------------------------ arm64-linux ------------------------- */
764
765#if defined(PLAT_arm64_linux)
766
767typedef
768 struct {
florian3540ee82014-11-19 07:41:19 +0000769 unsigned long int nraddr; /* where's the code? */
sewardjf0c12502014-01-12 12:54:00 +0000770 }
771 OrigFn;
772
773#define __SPECIAL_INSTRUCTION_PREAMBLE \
774 "ror x12, x12, #3 ; ror x12, x12, #13 \n\t" \
775 "ror x12, x12, #51 ; ror x12, x12, #61 \n\t"
776
777#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
778 _zzq_default, _zzq_request, \
779 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
780 \
781 __extension__ \
florian3540ee82014-11-19 07:41:19 +0000782 ({volatile unsigned long int _zzq_args[6]; \
783 volatile unsigned long int _zzq_result; \
784 _zzq_args[0] = (unsigned long int)(_zzq_request); \
785 _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
786 _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
787 _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
788 _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
789 _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
sewardjf0c12502014-01-12 12:54:00 +0000790 __asm__ volatile("mov x3, %1\n\t" /*default*/ \
791 "mov x4, %2\n\t" /*ptr*/ \
792 __SPECIAL_INSTRUCTION_PREAMBLE \
793 /* X3 = client_request ( X4 ) */ \
794 "orr x10, x10, x10\n\t" \
795 "mov %0, x3" /*result*/ \
796 : "=r" (_zzq_result) \
797 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
798 : "cc","memory", "x3", "x4"); \
799 _zzq_result; \
800 })
801
802#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
803 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
florian3540ee82014-11-19 07:41:19 +0000804 unsigned long int __addr; \
sewardjf0c12502014-01-12 12:54:00 +0000805 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
806 /* X3 = guest_NRADDR */ \
807 "orr x11, x11, x11\n\t" \
808 "mov %0, x3" \
809 : "=r" (__addr) \
810 : \
811 : "cc", "memory", "x3" \
812 ); \
813 _zzq_orig->nraddr = __addr; \
814 }
815
816#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
817 __SPECIAL_INSTRUCTION_PREAMBLE \
818 /* branch-and-link-to-noredir X8 */ \
819 "orr x12, x12, x12\n\t"
820
821#define VALGRIND_VEX_INJECT_IR() \
822 do { \
823 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
824 "orr x9, x9, x9\n\t" \
825 : : : "cc", "memory" \
826 ); \
827 } while (0)
828
829#endif /* PLAT_arm64_linux */
830
sewardjb5b87402011-03-07 16:05:35 +0000831/* ------------------------ s390x-linux ------------------------ */
832
833#if defined(PLAT_s390x_linux)
834
835typedef
836 struct {
florian3540ee82014-11-19 07:41:19 +0000837 unsigned long int nraddr; /* where's the code? */
sewardjb5b87402011-03-07 16:05:35 +0000838 }
839 OrigFn;
840
841/* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific
842 * code. This detection is implemented in platform specific toIR.c
843 * (e.g. VEX/priv/guest_s390_decoder.c).
844 */
845#define __SPECIAL_INSTRUCTION_PREAMBLE \
846 "lr 15,15\n\t" \
847 "lr 1,1\n\t" \
848 "lr 2,2\n\t" \
849 "lr 3,3\n\t"
850
851#define __CLIENT_REQUEST_CODE "lr 2,2\n\t"
852#define __GET_NR_CONTEXT_CODE "lr 3,3\n\t"
853#define __CALL_NO_REDIR_CODE "lr 4,4\n\t"
florianbb913cd2012-08-28 16:50:39 +0000854#define __VEX_INJECT_IR_CODE "lr 5,5\n\t"
sewardjb5b87402011-03-07 16:05:35 +0000855
bart575ce8e2011-05-15 07:04:03 +0000856#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
857 _zzq_default, _zzq_request, \
sewardjb5b87402011-03-07 16:05:35 +0000858 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000859 __extension__ \
florian3540ee82014-11-19 07:41:19 +0000860 ({volatile unsigned long int _zzq_args[6]; \
861 volatile unsigned long int _zzq_result; \
862 _zzq_args[0] = (unsigned long int)(_zzq_request); \
863 _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
864 _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
865 _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
866 _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
867 _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
sewardjb5b87402011-03-07 16:05:35 +0000868 __asm__ volatile(/* r2 = args */ \
869 "lgr 2,%1\n\t" \
870 /* r3 = default */ \
871 "lgr 3,%2\n\t" \
872 __SPECIAL_INSTRUCTION_PREAMBLE \
873 __CLIENT_REQUEST_CODE \
874 /* results = r3 */ \
875 "lgr %0, 3\n\t" \
876 : "=d" (_zzq_result) \
877 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
878 : "cc", "2", "3", "memory" \
879 ); \
bart575ce8e2011-05-15 07:04:03 +0000880 _zzq_result; \
881 })
sewardjb5b87402011-03-07 16:05:35 +0000882
883#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
884 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
florian3540ee82014-11-19 07:41:19 +0000885 volatile unsigned long int __addr; \
sewardjb5b87402011-03-07 16:05:35 +0000886 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
887 __GET_NR_CONTEXT_CODE \
888 "lgr %0, 3\n\t" \
889 : "=a" (__addr) \
890 : \
891 : "cc", "3", "memory" \
892 ); \
893 _zzq_orig->nraddr = __addr; \
894 }
895
896#define VALGRIND_CALL_NOREDIR_R1 \
897 __SPECIAL_INSTRUCTION_PREAMBLE \
898 __CALL_NO_REDIR_CODE
899
florianbb913cd2012-08-28 16:50:39 +0000900#define VALGRIND_VEX_INJECT_IR() \
901 do { \
902 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
903 __VEX_INJECT_IR_CODE); \
904 } while (0)
905
sewardjb5b87402011-03-07 16:05:35 +0000906#endif /* PLAT_s390x_linux */
907
sewardj5db15402012-06-07 09:13:21 +0000908/* ------------------------- mips32-linux ---------------- */
909
910#if defined(PLAT_mips32_linux)
911
912typedef
913 struct {
914 unsigned int nraddr; /* where's the code? */
915 }
916 OrigFn;
917
918/* .word 0x342
919 * .word 0x742
920 * .word 0xC2
921 * .word 0x4C2*/
922#define __SPECIAL_INSTRUCTION_PREAMBLE \
923 "srl $0, $0, 13\n\t" \
924 "srl $0, $0, 29\n\t" \
925 "srl $0, $0, 3\n\t" \
926 "srl $0, $0, 19\n\t"
927
928#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
929 _zzq_default, _zzq_request, \
930 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
931 __extension__ \
932 ({ volatile unsigned int _zzq_args[6]; \
933 volatile unsigned int _zzq_result; \
934 _zzq_args[0] = (unsigned int)(_zzq_request); \
935 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
936 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
937 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
938 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
939 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
940 __asm__ volatile("move $11, %1\n\t" /*default*/ \
941 "move $12, %2\n\t" /*ptr*/ \
942 __SPECIAL_INSTRUCTION_PREAMBLE \
943 /* T3 = client_request ( T4 ) */ \
944 "or $13, $13, $13\n\t" \
945 "move %0, $11\n\t" /*result*/ \
946 : "=r" (_zzq_result) \
947 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
petarj4df0bfc2013-02-27 23:17:33 +0000948 : "$11", "$12"); \
sewardj5db15402012-06-07 09:13:21 +0000949 _zzq_result; \
950 })
951
952#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
953 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
954 volatile unsigned int __addr; \
955 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
956 /* %t9 = guest_NRADDR */ \
957 "or $14, $14, $14\n\t" \
958 "move %0, $11" /*result*/ \
959 : "=r" (__addr) \
960 : \
petarj4df0bfc2013-02-27 23:17:33 +0000961 : "$11" \
sewardj5db15402012-06-07 09:13:21 +0000962 ); \
963 _zzq_orig->nraddr = __addr; \
964 }
965
966#define VALGRIND_CALL_NOREDIR_T9 \
967 __SPECIAL_INSTRUCTION_PREAMBLE \
968 /* call-noredir *%t9 */ \
florianbb913cd2012-08-28 16:50:39 +0000969 "or $15, $15, $15\n\t"
970
971#define VALGRIND_VEX_INJECT_IR() \
972 do { \
973 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
974 "or $11, $11, $11\n\t" \
975 ); \
976 } while (0)
977
978
sewardj5db15402012-06-07 09:13:21 +0000979#endif /* PLAT_mips32_linux */
980
petarj4df0bfc2013-02-27 23:17:33 +0000981/* ------------------------- mips64-linux ---------------- */
982
983#if defined(PLAT_mips64_linux)
984
985typedef
986 struct {
florian3540ee82014-11-19 07:41:19 +0000987 unsigned long nraddr; /* where's the code? */
petarj4df0bfc2013-02-27 23:17:33 +0000988 }
989 OrigFn;
990
991/* dsll $0,$0, 3
992 * dsll $0,$0, 13
993 * dsll $0,$0, 29
994 * dsll $0,$0, 19*/
995#define __SPECIAL_INSTRUCTION_PREAMBLE \
996 "dsll $0,$0, 3 ; dsll $0,$0,13\n\t" \
997 "dsll $0,$0,29 ; dsll $0,$0,19\n\t"
998
999#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
1000 _zzq_default, _zzq_request, \
1001 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
1002 __extension__ \
florian3540ee82014-11-19 07:41:19 +00001003 ({ volatile unsigned long int _zzq_args[6]; \
1004 volatile unsigned long int _zzq_result; \
1005 _zzq_args[0] = (unsigned long int)(_zzq_request); \
1006 _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
1007 _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
1008 _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
1009 _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
1010 _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
petarj4df0bfc2013-02-27 23:17:33 +00001011 __asm__ volatile("move $11, %1\n\t" /*default*/ \
1012 "move $12, %2\n\t" /*ptr*/ \
1013 __SPECIAL_INSTRUCTION_PREAMBLE \
1014 /* $11 = client_request ( $12 ) */ \
1015 "or $13, $13, $13\n\t" \
1016 "move %0, $11\n\t" /*result*/ \
1017 : "=r" (_zzq_result) \
1018 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
1019 : "$11", "$12"); \
1020 _zzq_result; \
1021 })
1022
1023#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
1024 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
florian3540ee82014-11-19 07:41:19 +00001025 volatile unsigned long int __addr; \
petarj4df0bfc2013-02-27 23:17:33 +00001026 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1027 /* $11 = guest_NRADDR */ \
1028 "or $14, $14, $14\n\t" \
1029 "move %0, $11" /*result*/ \
1030 : "=r" (__addr) \
1031 : \
1032 : "$11"); \
1033 _zzq_orig->nraddr = __addr; \
1034 }
1035
1036#define VALGRIND_CALL_NOREDIR_T9 \
1037 __SPECIAL_INSTRUCTION_PREAMBLE \
1038 /* call-noredir $25 */ \
1039 "or $15, $15, $15\n\t"
1040
1041#define VALGRIND_VEX_INJECT_IR() \
1042 do { \
1043 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1044 "or $11, $11, $11\n\t" \
1045 ); \
1046 } while (0)
1047
1048#endif /* PLAT_mips64_linux */
1049
sewardj112711a2015-04-10 12:30:09 +00001050/* ------------------------ tilegx-linux --------------- */
1051#if defined(PLAT_tilegx_linux)
1052
1053typedef
1054 struct {
1055 unsigned long long int nraddr; /* where's the code? */
1056 }
1057 OrigFn;
1058/*** special instruction sequence.
1059 0:02b3c7ff91234fff { moveli zero, 4660 ; moveli zero, 22136 }
1060 8:0091a7ff95678fff { moveli zero, 22136 ; moveli zero, 4660 }
1061****/
1062
1063#define __SPECIAL_INSTRUCTION_PREAMBLE \
1064 ".quad 0x02b3c7ff91234fff\n" \
1065 ".quad 0x0091a7ff95678fff\n"
1066
1067#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
1068 _zzq_default, _zzq_request, \
1069 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
1070 ({ volatile unsigned long long int _zzq_args[6]; \
1071 volatile unsigned long long int _zzq_result; \
1072 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
1073 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
1074 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
1075 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
1076 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
1077 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
1078 __asm__ volatile("move r11, %1\n\t" /*default*/ \
1079 "move r12, %2\n\t" /*ptr*/ \
1080 __SPECIAL_INSTRUCTION_PREAMBLE \
1081 /* r11 = client_request */ \
1082 "or r13, r13, r13\n\t" \
1083 "move %0, r11\n\t" /*result*/ \
1084 : "=r" (_zzq_result) \
1085 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
1086 : "memory", "r11", "r12"); \
1087 _zzq_result; \
1088 })
1089
1090#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
1091 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
1092 volatile unsigned long long int __addr; \
1093 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1094 /* r11 = guest_NRADDR */ \
1095 "or r14, r14, r14\n" \
1096 "move %0, r11\n" \
1097 : "=r" (__addr) \
1098 : \
1099 : "memory", "r11" \
1100 ); \
1101 _zzq_orig->nraddr = __addr; \
1102 }
1103
1104#define VALGRIND_CALL_NOREDIR_R12 \
1105 __SPECIAL_INSTRUCTION_PREAMBLE \
1106 "or r15, r15, r15\n\t"
1107
1108#define VALGRIND_VEX_INJECT_IR() \
1109 do { \
1110 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1111 "or r11, r11, r11\n\t" \
1112 ); \
1113 } while (0)
1114
1115#endif /* PLAT_tilegx_linux */
1116
sewardjf5c1a7f2006-10-17 01:32:48 +00001117/* Insert assembly code for other platforms here... */
njn26aba4d2005-05-16 13:31:23 +00001118
sewardj37091fb2002-11-16 11:06:50 +00001119#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +00001120
nethercote69d9c462004-10-26 13:00:12 +00001121
njn30d76c62005-06-18 15:07:39 +00001122/* ------------------------------------------------------------------ */
sewardjf5c1a7f2006-10-17 01:32:48 +00001123/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
sewardj0ec07f32006-01-12 12:32:32 +00001124/* ugly. It's the least-worst tradeoff I can think of. */
1125/* ------------------------------------------------------------------ */
1126
1127/* This section defines magic (a.k.a appalling-hack) macros for doing
1128 guaranteed-no-redirection macros, so as to get from function
1129 wrappers to the functions they are wrapping. The whole point is to
1130 construct standard call sequences, but to do the call itself with a
1131 special no-redirect call pseudo-instruction that the JIT
1132 understands and handles specially. This section is long and
1133 repetitious, and I can't see a way to make it shorter.
1134
1135 The naming scheme is as follows:
1136
1137 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
1138
1139 'W' stands for "word" and 'v' for "void". Hence there are
1140 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
1141 and for each, the possibility of returning a word-typed result, or
1142 no result.
1143*/
1144
1145/* Use these to write the name of your wrapper. NOTE: duplicates
sewardj85cf9002011-08-16 09:54:00 +00001146 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. NOTE also: inserts
1147 the default behaviour equivalance class tag "0000" into the name.
1148 See pub_tool_redir.h for details -- normally you don't need to
1149 think about this, though. */
sewardj0ec07f32006-01-12 12:32:32 +00001150
njn5f5ef2a2009-05-11 08:01:09 +00001151/* Use an extra level of macroisation so as to ensure the soname/fnname
1152 args are fully macro-expanded before pasting them together. */
1153#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
1154
sewardj0ec07f32006-01-12 12:32:32 +00001155#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +00001156 VG_CONCAT4(_vgw00000ZU_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +00001157
1158#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +00001159 VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +00001160
sewardjd68ac3e2006-01-20 14:31:57 +00001161/* Use this macro from within a wrapper function to collect the
1162 context (address and possibly other info) of the original function.
1163 Once you have that you can then use it in one of the CALL_FN_
1164 macros. The type of the argument _lval is OrigFn. */
1165#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +00001166
sewardj573f8bc2012-06-05 07:12:15 +00001167/* Also provide end-user facilities for function replacement, rather
1168 than wrapping. A replacement function differs from a wrapper in
1169 that it has no way to get hold of the original function being
1170 called, and hence no way to call onwards to it. In a replacement
1171 function, VALGRIND_GET_ORIG_FN always returns zero. */
1172
1173#define I_REPLACE_SONAME_FNNAME_ZU(soname,fnname) \
1174 VG_CONCAT4(_vgr00000ZU_,soname,_,fnname)
1175
1176#define I_REPLACE_SONAME_FNNAME_ZZ(soname,fnname) \
1177 VG_CONCAT4(_vgr00000ZZ_,soname,_,fnname)
1178
sewardj0ec07f32006-01-12 12:32:32 +00001179/* Derivatives of the main macros below, for calling functions
1180 returning void. */
1181
1182#define CALL_FN_v_v(fnptr) \
1183 do { volatile unsigned long _junk; \
1184 CALL_FN_W_v(_junk,fnptr); } while (0)
1185
1186#define CALL_FN_v_W(fnptr, arg1) \
1187 do { volatile unsigned long _junk; \
1188 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
1189
1190#define CALL_FN_v_WW(fnptr, arg1,arg2) \
1191 do { volatile unsigned long _junk; \
1192 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
1193
sewardj5ce4b152006-03-11 12:57:41 +00001194#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
1195 do { volatile unsigned long _junk; \
1196 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
1197
njn2b5f0a92009-05-19 01:24:50 +00001198#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
1199 do { volatile unsigned long _junk; \
1200 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
1201
1202#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
1203 do { volatile unsigned long _junk; \
1204 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
1205
1206#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
1207 do { volatile unsigned long _junk; \
1208 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
1209
1210#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
1211 do { volatile unsigned long _junk; \
1212 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
1213
sewardj8eb8bab2015-07-21 14:44:28 +00001214/* ----------------- x86-{linux,darwin,solaris} ---------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001215
sewardj8eb8bab2015-07-21 14:44:28 +00001216#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
1217 || defined(PLAT_x86_solaris)
sewardj0ec07f32006-01-12 12:32:32 +00001218
1219/* These regs are trashed by the hidden call. No need to mention eax
1220 as gcc can already see that, plus causes gcc to bomb. */
1221#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
1222
tom4118e0f2012-08-02 09:23:45 +00001223/* Macros to save and align the stack before making a function
1224 call and restore it afterwards as gcc may not keep the stack
1225 pointer aligned if it doesn't realise calls are being made
1226 to other functions. */
1227
1228#define VALGRIND_ALIGN_STACK \
1229 "movl %%esp,%%edi\n\t" \
1230 "andl $0xfffffff0,%%esp\n\t"
1231#define VALGRIND_RESTORE_STACK \
1232 "movl %%edi,%%esp\n\t"
1233
sewardj0ec07f32006-01-12 12:32:32 +00001234/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
1235 long) == 4. */
1236
sewardj66226cc2006-01-20 15:46:46 +00001237#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001238 do { \
sewardj66226cc2006-01-20 15:46:46 +00001239 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001240 volatile unsigned long _argvec[1]; \
1241 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001242 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001243 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001244 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001245 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1246 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001247 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001248 : /*out*/ "=a" (_res) \
1249 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001250 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001251 ); \
1252 lval = (__typeof__(lval)) _res; \
1253 } while (0)
1254
sewardj66226cc2006-01-20 15:46:46 +00001255#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001256 do { \
sewardj66226cc2006-01-20 15:46:46 +00001257 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001258 volatile unsigned long _argvec[2]; \
1259 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001260 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001261 _argvec[1] = (unsigned long)(arg1); \
1262 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001263 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001264 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001265 "pushl 4(%%eax)\n\t" \
1266 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1267 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001268 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001269 : /*out*/ "=a" (_res) \
1270 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001271 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001272 ); \
1273 lval = (__typeof__(lval)) _res; \
1274 } while (0)
1275
sewardj66226cc2006-01-20 15:46:46 +00001276#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001277 do { \
sewardj66226cc2006-01-20 15:46:46 +00001278 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001279 volatile unsigned long _argvec[3]; \
1280 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001281 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001282 _argvec[1] = (unsigned long)(arg1); \
1283 _argvec[2] = (unsigned long)(arg2); \
1284 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001285 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001286 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001287 "pushl 8(%%eax)\n\t" \
1288 "pushl 4(%%eax)\n\t" \
1289 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1290 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001291 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001292 : /*out*/ "=a" (_res) \
1293 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001294 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001295 ); \
1296 lval = (__typeof__(lval)) _res; \
1297 } while (0)
1298
sewardj9e8b07a2006-02-18 21:13:29 +00001299#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1300 do { \
1301 volatile OrigFn _orig = (orig); \
1302 volatile unsigned long _argvec[4]; \
1303 volatile unsigned long _res; \
1304 _argvec[0] = (unsigned long)_orig.nraddr; \
1305 _argvec[1] = (unsigned long)(arg1); \
1306 _argvec[2] = (unsigned long)(arg2); \
1307 _argvec[3] = (unsigned long)(arg3); \
1308 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001309 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001310 "subl $4, %%esp\n\t" \
sewardj9e8b07a2006-02-18 21:13:29 +00001311 "pushl 12(%%eax)\n\t" \
1312 "pushl 8(%%eax)\n\t" \
1313 "pushl 4(%%eax)\n\t" \
1314 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1315 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001316 VALGRIND_RESTORE_STACK \
sewardj9e8b07a2006-02-18 21:13:29 +00001317 : /*out*/ "=a" (_res) \
1318 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001319 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj9e8b07a2006-02-18 21:13:29 +00001320 ); \
1321 lval = (__typeof__(lval)) _res; \
1322 } while (0)
1323
sewardj66226cc2006-01-20 15:46:46 +00001324#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
sewardj0ec07f32006-01-12 12:32:32 +00001325 do { \
sewardj66226cc2006-01-20 15:46:46 +00001326 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001327 volatile unsigned long _argvec[5]; \
1328 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001329 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001330 _argvec[1] = (unsigned long)(arg1); \
1331 _argvec[2] = (unsigned long)(arg2); \
1332 _argvec[3] = (unsigned long)(arg3); \
1333 _argvec[4] = (unsigned long)(arg4); \
1334 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001335 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001336 "pushl 16(%%eax)\n\t" \
1337 "pushl 12(%%eax)\n\t" \
1338 "pushl 8(%%eax)\n\t" \
1339 "pushl 4(%%eax)\n\t" \
1340 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1341 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001342 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001343 : /*out*/ "=a" (_res) \
1344 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001345 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001346 ); \
1347 lval = (__typeof__(lval)) _res; \
1348 } while (0)
1349
sewardj66226cc2006-01-20 15:46:46 +00001350#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +00001351 do { \
sewardj66226cc2006-01-20 15:46:46 +00001352 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001353 volatile unsigned long _argvec[6]; \
1354 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001355 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001356 _argvec[1] = (unsigned long)(arg1); \
1357 _argvec[2] = (unsigned long)(arg2); \
1358 _argvec[3] = (unsigned long)(arg3); \
1359 _argvec[4] = (unsigned long)(arg4); \
1360 _argvec[5] = (unsigned long)(arg5); \
1361 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001362 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001363 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001364 "pushl 20(%%eax)\n\t" \
1365 "pushl 16(%%eax)\n\t" \
1366 "pushl 12(%%eax)\n\t" \
1367 "pushl 8(%%eax)\n\t" \
1368 "pushl 4(%%eax)\n\t" \
1369 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1370 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001371 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001372 : /*out*/ "=a" (_res) \
1373 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001374 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001375 ); \
1376 lval = (__typeof__(lval)) _res; \
1377 } while (0)
1378
sewardj66226cc2006-01-20 15:46:46 +00001379#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +00001380 do { \
sewardj66226cc2006-01-20 15:46:46 +00001381 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001382 volatile unsigned long _argvec[7]; \
1383 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001384 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001385 _argvec[1] = (unsigned long)(arg1); \
1386 _argvec[2] = (unsigned long)(arg2); \
1387 _argvec[3] = (unsigned long)(arg3); \
1388 _argvec[4] = (unsigned long)(arg4); \
1389 _argvec[5] = (unsigned long)(arg5); \
1390 _argvec[6] = (unsigned long)(arg6); \
1391 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001392 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001393 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001394 "pushl 24(%%eax)\n\t" \
1395 "pushl 20(%%eax)\n\t" \
1396 "pushl 16(%%eax)\n\t" \
1397 "pushl 12(%%eax)\n\t" \
1398 "pushl 8(%%eax)\n\t" \
1399 "pushl 4(%%eax)\n\t" \
1400 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1401 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001402 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001403 : /*out*/ "=a" (_res) \
1404 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001405 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001406 ); \
1407 lval = (__typeof__(lval)) _res; \
1408 } while (0)
1409
sewardj66226cc2006-01-20 15:46:46 +00001410#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1411 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +00001412 do { \
sewardj66226cc2006-01-20 15:46:46 +00001413 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001414 volatile unsigned long _argvec[8]; \
1415 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001416 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001417 _argvec[1] = (unsigned long)(arg1); \
1418 _argvec[2] = (unsigned long)(arg2); \
1419 _argvec[3] = (unsigned long)(arg3); \
1420 _argvec[4] = (unsigned long)(arg4); \
1421 _argvec[5] = (unsigned long)(arg5); \
1422 _argvec[6] = (unsigned long)(arg6); \
1423 _argvec[7] = (unsigned long)(arg7); \
1424 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001425 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001426 "subl $4, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001427 "pushl 28(%%eax)\n\t" \
1428 "pushl 24(%%eax)\n\t" \
1429 "pushl 20(%%eax)\n\t" \
1430 "pushl 16(%%eax)\n\t" \
1431 "pushl 12(%%eax)\n\t" \
1432 "pushl 8(%%eax)\n\t" \
1433 "pushl 4(%%eax)\n\t" \
1434 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1435 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001436 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001437 : /*out*/ "=a" (_res) \
1438 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001439 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001440 ); \
1441 lval = (__typeof__(lval)) _res; \
1442 } while (0)
1443
sewardj66226cc2006-01-20 15:46:46 +00001444#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1445 arg7,arg8) \
sewardj0ec07f32006-01-12 12:32:32 +00001446 do { \
sewardj66226cc2006-01-20 15:46:46 +00001447 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001448 volatile unsigned long _argvec[9]; \
1449 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001450 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001451 _argvec[1] = (unsigned long)(arg1); \
1452 _argvec[2] = (unsigned long)(arg2); \
1453 _argvec[3] = (unsigned long)(arg3); \
1454 _argvec[4] = (unsigned long)(arg4); \
1455 _argvec[5] = (unsigned long)(arg5); \
1456 _argvec[6] = (unsigned long)(arg6); \
1457 _argvec[7] = (unsigned long)(arg7); \
1458 _argvec[8] = (unsigned long)(arg8); \
1459 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001460 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001461 "pushl 32(%%eax)\n\t" \
1462 "pushl 28(%%eax)\n\t" \
1463 "pushl 24(%%eax)\n\t" \
1464 "pushl 20(%%eax)\n\t" \
1465 "pushl 16(%%eax)\n\t" \
1466 "pushl 12(%%eax)\n\t" \
1467 "pushl 8(%%eax)\n\t" \
1468 "pushl 4(%%eax)\n\t" \
1469 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1470 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001471 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001472 : /*out*/ "=a" (_res) \
1473 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001474 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001475 ); \
1476 lval = (__typeof__(lval)) _res; \
1477 } while (0)
1478
sewardj45fa5b02006-03-09 19:06:23 +00001479#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1480 arg7,arg8,arg9) \
1481 do { \
1482 volatile OrigFn _orig = (orig); \
1483 volatile unsigned long _argvec[10]; \
1484 volatile unsigned long _res; \
1485 _argvec[0] = (unsigned long)_orig.nraddr; \
1486 _argvec[1] = (unsigned long)(arg1); \
1487 _argvec[2] = (unsigned long)(arg2); \
1488 _argvec[3] = (unsigned long)(arg3); \
1489 _argvec[4] = (unsigned long)(arg4); \
1490 _argvec[5] = (unsigned long)(arg5); \
1491 _argvec[6] = (unsigned long)(arg6); \
1492 _argvec[7] = (unsigned long)(arg7); \
1493 _argvec[8] = (unsigned long)(arg8); \
1494 _argvec[9] = (unsigned long)(arg9); \
1495 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001496 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001497 "subl $12, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001498 "pushl 36(%%eax)\n\t" \
1499 "pushl 32(%%eax)\n\t" \
1500 "pushl 28(%%eax)\n\t" \
1501 "pushl 24(%%eax)\n\t" \
1502 "pushl 20(%%eax)\n\t" \
1503 "pushl 16(%%eax)\n\t" \
1504 "pushl 12(%%eax)\n\t" \
1505 "pushl 8(%%eax)\n\t" \
1506 "pushl 4(%%eax)\n\t" \
1507 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1508 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001509 VALGRIND_RESTORE_STACK \
sewardj45fa5b02006-03-09 19:06:23 +00001510 : /*out*/ "=a" (_res) \
1511 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001512 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj45fa5b02006-03-09 19:06:23 +00001513 ); \
1514 lval = (__typeof__(lval)) _res; \
1515 } while (0)
1516
1517#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1518 arg7,arg8,arg9,arg10) \
1519 do { \
1520 volatile OrigFn _orig = (orig); \
1521 volatile unsigned long _argvec[11]; \
1522 volatile unsigned long _res; \
1523 _argvec[0] = (unsigned long)_orig.nraddr; \
1524 _argvec[1] = (unsigned long)(arg1); \
1525 _argvec[2] = (unsigned long)(arg2); \
1526 _argvec[3] = (unsigned long)(arg3); \
1527 _argvec[4] = (unsigned long)(arg4); \
1528 _argvec[5] = (unsigned long)(arg5); \
1529 _argvec[6] = (unsigned long)(arg6); \
1530 _argvec[7] = (unsigned long)(arg7); \
1531 _argvec[8] = (unsigned long)(arg8); \
1532 _argvec[9] = (unsigned long)(arg9); \
1533 _argvec[10] = (unsigned long)(arg10); \
1534 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001535 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001536 "subl $8, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001537 "pushl 40(%%eax)\n\t" \
1538 "pushl 36(%%eax)\n\t" \
1539 "pushl 32(%%eax)\n\t" \
1540 "pushl 28(%%eax)\n\t" \
1541 "pushl 24(%%eax)\n\t" \
1542 "pushl 20(%%eax)\n\t" \
1543 "pushl 16(%%eax)\n\t" \
1544 "pushl 12(%%eax)\n\t" \
1545 "pushl 8(%%eax)\n\t" \
1546 "pushl 4(%%eax)\n\t" \
1547 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1548 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001549 VALGRIND_RESTORE_STACK \
sewardj45fa5b02006-03-09 19:06:23 +00001550 : /*out*/ "=a" (_res) \
1551 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001552 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj45fa5b02006-03-09 19:06:23 +00001553 ); \
1554 lval = (__typeof__(lval)) _res; \
1555 } while (0)
1556
sewardj5ce4b152006-03-11 12:57:41 +00001557#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1558 arg6,arg7,arg8,arg9,arg10, \
1559 arg11) \
1560 do { \
1561 volatile OrigFn _orig = (orig); \
1562 volatile unsigned long _argvec[12]; \
1563 volatile unsigned long _res; \
1564 _argvec[0] = (unsigned long)_orig.nraddr; \
1565 _argvec[1] = (unsigned long)(arg1); \
1566 _argvec[2] = (unsigned long)(arg2); \
1567 _argvec[3] = (unsigned long)(arg3); \
1568 _argvec[4] = (unsigned long)(arg4); \
1569 _argvec[5] = (unsigned long)(arg5); \
1570 _argvec[6] = (unsigned long)(arg6); \
1571 _argvec[7] = (unsigned long)(arg7); \
1572 _argvec[8] = (unsigned long)(arg8); \
1573 _argvec[9] = (unsigned long)(arg9); \
1574 _argvec[10] = (unsigned long)(arg10); \
1575 _argvec[11] = (unsigned long)(arg11); \
1576 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001577 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001578 "subl $4, %%esp\n\t" \
sewardj5ce4b152006-03-11 12:57:41 +00001579 "pushl 44(%%eax)\n\t" \
1580 "pushl 40(%%eax)\n\t" \
1581 "pushl 36(%%eax)\n\t" \
1582 "pushl 32(%%eax)\n\t" \
1583 "pushl 28(%%eax)\n\t" \
1584 "pushl 24(%%eax)\n\t" \
1585 "pushl 20(%%eax)\n\t" \
1586 "pushl 16(%%eax)\n\t" \
1587 "pushl 12(%%eax)\n\t" \
1588 "pushl 8(%%eax)\n\t" \
1589 "pushl 4(%%eax)\n\t" \
1590 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1591 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001592 VALGRIND_RESTORE_STACK \
sewardj5ce4b152006-03-11 12:57:41 +00001593 : /*out*/ "=a" (_res) \
1594 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001595 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj5ce4b152006-03-11 12:57:41 +00001596 ); \
1597 lval = (__typeof__(lval)) _res; \
1598 } while (0)
1599
sewardj66226cc2006-01-20 15:46:46 +00001600#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1601 arg6,arg7,arg8,arg9,arg10, \
1602 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +00001603 do { \
sewardj66226cc2006-01-20 15:46:46 +00001604 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001605 volatile unsigned long _argvec[13]; \
1606 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001607 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001608 _argvec[1] = (unsigned long)(arg1); \
1609 _argvec[2] = (unsigned long)(arg2); \
1610 _argvec[3] = (unsigned long)(arg3); \
1611 _argvec[4] = (unsigned long)(arg4); \
1612 _argvec[5] = (unsigned long)(arg5); \
1613 _argvec[6] = (unsigned long)(arg6); \
1614 _argvec[7] = (unsigned long)(arg7); \
1615 _argvec[8] = (unsigned long)(arg8); \
1616 _argvec[9] = (unsigned long)(arg9); \
1617 _argvec[10] = (unsigned long)(arg10); \
1618 _argvec[11] = (unsigned long)(arg11); \
1619 _argvec[12] = (unsigned long)(arg12); \
1620 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001621 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001622 "pushl 48(%%eax)\n\t" \
1623 "pushl 44(%%eax)\n\t" \
1624 "pushl 40(%%eax)\n\t" \
1625 "pushl 36(%%eax)\n\t" \
1626 "pushl 32(%%eax)\n\t" \
1627 "pushl 28(%%eax)\n\t" \
1628 "pushl 24(%%eax)\n\t" \
1629 "pushl 20(%%eax)\n\t" \
1630 "pushl 16(%%eax)\n\t" \
1631 "pushl 12(%%eax)\n\t" \
1632 "pushl 8(%%eax)\n\t" \
1633 "pushl 4(%%eax)\n\t" \
1634 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1635 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001636 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001637 : /*out*/ "=a" (_res) \
1638 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001639 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001640 ); \
1641 lval = (__typeof__(lval)) _res; \
1642 } while (0)
1643
sewardj8eb8bab2015-07-21 14:44:28 +00001644#endif /* PLAT_x86_linux || PLAT_x86_darwin || PLAT_x86_solaris */
sewardj0ec07f32006-01-12 12:32:32 +00001645
sewardj8eb8bab2015-07-21 14:44:28 +00001646/* ---------------- amd64-{linux,darwin,solaris} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001647
sewardj8eb8bab2015-07-21 14:44:28 +00001648#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \
1649 || defined(PLAT_amd64_solaris)
sewardj0ec07f32006-01-12 12:32:32 +00001650
1651/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1652
1653/* These regs are trashed by the hidden call. */
1654#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1655 "rdi", "r8", "r9", "r10", "r11"
1656
sewardjdfa55cf2010-10-06 22:07:06 +00001657/* This is all pretty complex. It's so as to make stack unwinding
1658 work reliably. See bug 243270. The basic problem is the sub and
1659 add of 128 of %rsp in all of the following macros. If gcc believes
1660 the CFA is in %rsp, then unwinding may fail, because what's at the
1661 CFA is not what gcc "expected" when it constructs the CFIs for the
1662 places where the macros are instantiated.
1663
1664 But we can't just add a CFI annotation to increase the CFA offset
1665 by 128, to match the sub of 128 from %rsp, because we don't know
1666 whether gcc has chosen %rsp as the CFA at that point, or whether it
1667 has chosen some other register (eg, %rbp). In the latter case,
1668 adding a CFI annotation to change the CFA offset is simply wrong.
1669
1670 So the solution is to get hold of the CFA using
sewardj8d1dc152010-10-08 17:43:26 +00001671 __builtin_dwarf_cfa(), put it in a known register, and add a
sewardjdfa55cf2010-10-06 22:07:06 +00001672 CFI annotation to say what the register is. We choose %rbp for
1673 this (perhaps perversely), because:
1674
1675 (1) %rbp is already subject to unwinding. If a new register was
1676 chosen then the unwinder would have to unwind it in all stack
1677 traces, which is expensive, and
1678
1679 (2) %rbp is already subject to precise exception updates in the
1680 JIT. If a new register was chosen, we'd have to have precise
1681 exceptions for it too, which reduces performance of the
1682 generated code.
1683
1684 However .. one extra complication. We can't just whack the result
sewardj8d1dc152010-10-08 17:43:26 +00001685 of __builtin_dwarf_cfa() into %rbp and then add %rbp to the
sewardjdfa55cf2010-10-06 22:07:06 +00001686 list of trashed registers at the end of the inline assembly
1687 fragments; gcc won't allow %rbp to appear in that list. Hence
1688 instead we need to stash %rbp in %r15 for the duration of the asm,
1689 and say that %r15 is trashed instead. gcc seems happy to go with
1690 that.
1691
1692 Oh .. and this all needs to be conditionalised so that it is
1693 unchanged from before this commit, when compiled with older gccs
sewardj8d1dc152010-10-08 17:43:26 +00001694 that don't support __builtin_dwarf_cfa. Furthermore, since
1695 this header file is freestanding, it has to be independent of
1696 config.h, and so the following conditionalisation cannot depend on
1697 configure time checks.
1698
1699 Although it's not clear from
1700 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)',
1701 this expression excludes Darwin.
1702 .cfi directives in Darwin assembly appear to be completely
1703 different and I haven't investigated how they work.
1704
1705 For even more entertainment value, note we have to use the
1706 completely undocumented __builtin_dwarf_cfa(), which appears to
1707 really compute the CFA, whereas __builtin_frame_address(0) claims
1708 to but actually doesn't. See
1709 https://bugs.kde.org/show_bug.cgi?id=243270#c47
sewardjdfa55cf2010-10-06 22:07:06 +00001710*/
sewardj8d1dc152010-10-08 17:43:26 +00001711#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
sewardjdfa55cf2010-10-06 22:07:06 +00001712# define __FRAME_POINTER \
sewardj8d1dc152010-10-08 17:43:26 +00001713 ,"r"(__builtin_dwarf_cfa())
sewardjdfa55cf2010-10-06 22:07:06 +00001714# define VALGRIND_CFI_PROLOGUE \
sewardjdfa55cf2010-10-06 22:07:06 +00001715 "movq %%rbp, %%r15\n\t" \
sewardj8d1dc152010-10-08 17:43:26 +00001716 "movq %2, %%rbp\n\t" \
1717 ".cfi_remember_state\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001718 ".cfi_def_cfa rbp, 0\n\t"
1719# define VALGRIND_CFI_EPILOGUE \
1720 "movq %%r15, %%rbp\n\t" \
1721 ".cfi_restore_state\n\t"
1722#else
1723# define __FRAME_POINTER
1724# define VALGRIND_CFI_PROLOGUE
1725# define VALGRIND_CFI_EPILOGUE
1726#endif
1727
tom4118e0f2012-08-02 09:23:45 +00001728/* Macros to save and align the stack before making a function
1729 call and restore it afterwards as gcc may not keep the stack
1730 pointer aligned if it doesn't realise calls are being made
1731 to other functions. */
1732
1733#define VALGRIND_ALIGN_STACK \
1734 "movq %%rsp,%%r14\n\t" \
1735 "andq $0xfffffffffffffff0,%%rsp\n\t"
1736#define VALGRIND_RESTORE_STACK \
1737 "movq %%r14,%%rsp\n\t"
sewardjdfa55cf2010-10-06 22:07:06 +00001738
sewardj0ec07f32006-01-12 12:32:32 +00001739/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1740 long) == 8. */
1741
sewardja07c2e12007-11-09 23:09:50 +00001742/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1743 macros. In order not to trash the stack redzone, we need to drop
1744 %rsp by 128 before the hidden call, and restore afterwards. The
1745 nastyness is that it is only by luck that the stack still appears
1746 to be unwindable during the hidden call - since then the behaviour
1747 of any routine using this macro does not match what the CFI data
1748 says. Sigh.
1749
1750 Why is this important? Imagine that a wrapper has a stack
1751 allocated local, and passes to the hidden call, a pointer to it.
1752 Because gcc does not know about the hidden call, it may allocate
1753 that local in the redzone. Unfortunately the hidden call may then
1754 trash it before it comes to use it. So we must step clear of the
1755 redzone, for the duration of the hidden call, to make it safe.
1756
1757 Probably the same problem afflicts the other redzone-style ABIs too
sewardj6e9de462011-06-28 07:25:29 +00001758 (ppc64-linux); but for those, the stack is
sewardja07c2e12007-11-09 23:09:50 +00001759 self describing (none of this CFI nonsense) so at least messing
1760 with the stack pointer doesn't give a danger of non-unwindable
1761 stack. */
1762
tom4118e0f2012-08-02 09:23:45 +00001763#define CALL_FN_W_v(lval, orig) \
1764 do { \
1765 volatile OrigFn _orig = (orig); \
1766 volatile unsigned long _argvec[1]; \
1767 volatile unsigned long _res; \
1768 _argvec[0] = (unsigned long)_orig.nraddr; \
1769 __asm__ volatile( \
1770 VALGRIND_CFI_PROLOGUE \
1771 VALGRIND_ALIGN_STACK \
1772 "subq $128,%%rsp\n\t" \
1773 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1774 VALGRIND_CALL_NOREDIR_RAX \
1775 VALGRIND_RESTORE_STACK \
1776 VALGRIND_CFI_EPILOGUE \
1777 : /*out*/ "=a" (_res) \
1778 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1779 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1780 ); \
1781 lval = (__typeof__(lval)) _res; \
sewardj0ec07f32006-01-12 12:32:32 +00001782 } while (0)
1783
tom4118e0f2012-08-02 09:23:45 +00001784#define CALL_FN_W_W(lval, orig, arg1) \
1785 do { \
1786 volatile OrigFn _orig = (orig); \
1787 volatile unsigned long _argvec[2]; \
1788 volatile unsigned long _res; \
1789 _argvec[0] = (unsigned long)_orig.nraddr; \
1790 _argvec[1] = (unsigned long)(arg1); \
1791 __asm__ volatile( \
1792 VALGRIND_CFI_PROLOGUE \
1793 VALGRIND_ALIGN_STACK \
1794 "subq $128,%%rsp\n\t" \
1795 "movq 8(%%rax), %%rdi\n\t" \
1796 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1797 VALGRIND_CALL_NOREDIR_RAX \
1798 VALGRIND_RESTORE_STACK \
1799 VALGRIND_CFI_EPILOGUE \
1800 : /*out*/ "=a" (_res) \
1801 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1802 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1803 ); \
1804 lval = (__typeof__(lval)) _res; \
sewardj0ec07f32006-01-12 12:32:32 +00001805 } while (0)
1806
tom4118e0f2012-08-02 09:23:45 +00001807#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1808 do { \
1809 volatile OrigFn _orig = (orig); \
1810 volatile unsigned long _argvec[3]; \
1811 volatile unsigned long _res; \
1812 _argvec[0] = (unsigned long)_orig.nraddr; \
1813 _argvec[1] = (unsigned long)(arg1); \
1814 _argvec[2] = (unsigned long)(arg2); \
1815 __asm__ volatile( \
1816 VALGRIND_CFI_PROLOGUE \
1817 VALGRIND_ALIGN_STACK \
1818 "subq $128,%%rsp\n\t" \
1819 "movq 16(%%rax), %%rsi\n\t" \
1820 "movq 8(%%rax), %%rdi\n\t" \
1821 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1822 VALGRIND_CALL_NOREDIR_RAX \
1823 VALGRIND_RESTORE_STACK \
1824 VALGRIND_CFI_EPILOGUE \
1825 : /*out*/ "=a" (_res) \
1826 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1827 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1828 ); \
1829 lval = (__typeof__(lval)) _res; \
sewardj0ec07f32006-01-12 12:32:32 +00001830 } while (0)
1831
tom4118e0f2012-08-02 09:23:45 +00001832#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1833 do { \
1834 volatile OrigFn _orig = (orig); \
1835 volatile unsigned long _argvec[4]; \
1836 volatile unsigned long _res; \
1837 _argvec[0] = (unsigned long)_orig.nraddr; \
1838 _argvec[1] = (unsigned long)(arg1); \
1839 _argvec[2] = (unsigned long)(arg2); \
1840 _argvec[3] = (unsigned long)(arg3); \
1841 __asm__ volatile( \
1842 VALGRIND_CFI_PROLOGUE \
1843 VALGRIND_ALIGN_STACK \
1844 "subq $128,%%rsp\n\t" \
1845 "movq 24(%%rax), %%rdx\n\t" \
1846 "movq 16(%%rax), %%rsi\n\t" \
1847 "movq 8(%%rax), %%rdi\n\t" \
1848 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1849 VALGRIND_CALL_NOREDIR_RAX \
1850 VALGRIND_RESTORE_STACK \
1851 VALGRIND_CFI_EPILOGUE \
1852 : /*out*/ "=a" (_res) \
1853 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1854 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1855 ); \
1856 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001857 } while (0)
1858
tom4118e0f2012-08-02 09:23:45 +00001859#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1860 do { \
1861 volatile OrigFn _orig = (orig); \
1862 volatile unsigned long _argvec[5]; \
1863 volatile unsigned long _res; \
1864 _argvec[0] = (unsigned long)_orig.nraddr; \
1865 _argvec[1] = (unsigned long)(arg1); \
1866 _argvec[2] = (unsigned long)(arg2); \
1867 _argvec[3] = (unsigned long)(arg3); \
1868 _argvec[4] = (unsigned long)(arg4); \
1869 __asm__ volatile( \
1870 VALGRIND_CFI_PROLOGUE \
1871 VALGRIND_ALIGN_STACK \
1872 "subq $128,%%rsp\n\t" \
1873 "movq 32(%%rax), %%rcx\n\t" \
1874 "movq 24(%%rax), %%rdx\n\t" \
1875 "movq 16(%%rax), %%rsi\n\t" \
1876 "movq 8(%%rax), %%rdi\n\t" \
1877 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1878 VALGRIND_CALL_NOREDIR_RAX \
1879 VALGRIND_RESTORE_STACK \
1880 VALGRIND_CFI_EPILOGUE \
1881 : /*out*/ "=a" (_res) \
1882 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1883 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1884 ); \
1885 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001886 } while (0)
1887
tom4118e0f2012-08-02 09:23:45 +00001888#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1889 do { \
1890 volatile OrigFn _orig = (orig); \
1891 volatile unsigned long _argvec[6]; \
1892 volatile unsigned long _res; \
1893 _argvec[0] = (unsigned long)_orig.nraddr; \
1894 _argvec[1] = (unsigned long)(arg1); \
1895 _argvec[2] = (unsigned long)(arg2); \
1896 _argvec[3] = (unsigned long)(arg3); \
1897 _argvec[4] = (unsigned long)(arg4); \
1898 _argvec[5] = (unsigned long)(arg5); \
1899 __asm__ volatile( \
1900 VALGRIND_CFI_PROLOGUE \
1901 VALGRIND_ALIGN_STACK \
1902 "subq $128,%%rsp\n\t" \
1903 "movq 40(%%rax), %%r8\n\t" \
1904 "movq 32(%%rax), %%rcx\n\t" \
1905 "movq 24(%%rax), %%rdx\n\t" \
1906 "movq 16(%%rax), %%rsi\n\t" \
1907 "movq 8(%%rax), %%rdi\n\t" \
1908 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1909 VALGRIND_CALL_NOREDIR_RAX \
1910 VALGRIND_RESTORE_STACK \
1911 VALGRIND_CFI_EPILOGUE \
1912 : /*out*/ "=a" (_res) \
1913 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1914 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1915 ); \
1916 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001917 } while (0)
1918
tom4118e0f2012-08-02 09:23:45 +00001919#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1920 do { \
1921 volatile OrigFn _orig = (orig); \
1922 volatile unsigned long _argvec[7]; \
1923 volatile unsigned long _res; \
1924 _argvec[0] = (unsigned long)_orig.nraddr; \
1925 _argvec[1] = (unsigned long)(arg1); \
1926 _argvec[2] = (unsigned long)(arg2); \
1927 _argvec[3] = (unsigned long)(arg3); \
1928 _argvec[4] = (unsigned long)(arg4); \
1929 _argvec[5] = (unsigned long)(arg5); \
1930 _argvec[6] = (unsigned long)(arg6); \
1931 __asm__ volatile( \
1932 VALGRIND_CFI_PROLOGUE \
1933 VALGRIND_ALIGN_STACK \
1934 "subq $128,%%rsp\n\t" \
1935 "movq 48(%%rax), %%r9\n\t" \
1936 "movq 40(%%rax), %%r8\n\t" \
1937 "movq 32(%%rax), %%rcx\n\t" \
1938 "movq 24(%%rax), %%rdx\n\t" \
1939 "movq 16(%%rax), %%rsi\n\t" \
1940 "movq 8(%%rax), %%rdi\n\t" \
1941 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1942 VALGRIND_CALL_NOREDIR_RAX \
1943 VALGRIND_RESTORE_STACK \
1944 VALGRIND_CFI_EPILOGUE \
1945 : /*out*/ "=a" (_res) \
1946 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1947 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1948 ); \
1949 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001950 } while (0)
1951
tom4118e0f2012-08-02 09:23:45 +00001952#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1953 arg7) \
1954 do { \
1955 volatile OrigFn _orig = (orig); \
1956 volatile unsigned long _argvec[8]; \
1957 volatile unsigned long _res; \
1958 _argvec[0] = (unsigned long)_orig.nraddr; \
1959 _argvec[1] = (unsigned long)(arg1); \
1960 _argvec[2] = (unsigned long)(arg2); \
1961 _argvec[3] = (unsigned long)(arg3); \
1962 _argvec[4] = (unsigned long)(arg4); \
1963 _argvec[5] = (unsigned long)(arg5); \
1964 _argvec[6] = (unsigned long)(arg6); \
1965 _argvec[7] = (unsigned long)(arg7); \
1966 __asm__ volatile( \
1967 VALGRIND_CFI_PROLOGUE \
1968 VALGRIND_ALIGN_STACK \
1969 "subq $136,%%rsp\n\t" \
1970 "pushq 56(%%rax)\n\t" \
1971 "movq 48(%%rax), %%r9\n\t" \
1972 "movq 40(%%rax), %%r8\n\t" \
1973 "movq 32(%%rax), %%rcx\n\t" \
1974 "movq 24(%%rax), %%rdx\n\t" \
1975 "movq 16(%%rax), %%rsi\n\t" \
1976 "movq 8(%%rax), %%rdi\n\t" \
1977 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1978 VALGRIND_CALL_NOREDIR_RAX \
1979 VALGRIND_RESTORE_STACK \
1980 VALGRIND_CFI_EPILOGUE \
1981 : /*out*/ "=a" (_res) \
1982 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1983 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1984 ); \
1985 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001986 } while (0)
1987
tom4118e0f2012-08-02 09:23:45 +00001988#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1989 arg7,arg8) \
1990 do { \
1991 volatile OrigFn _orig = (orig); \
1992 volatile unsigned long _argvec[9]; \
1993 volatile unsigned long _res; \
1994 _argvec[0] = (unsigned long)_orig.nraddr; \
1995 _argvec[1] = (unsigned long)(arg1); \
1996 _argvec[2] = (unsigned long)(arg2); \
1997 _argvec[3] = (unsigned long)(arg3); \
1998 _argvec[4] = (unsigned long)(arg4); \
1999 _argvec[5] = (unsigned long)(arg5); \
2000 _argvec[6] = (unsigned long)(arg6); \
2001 _argvec[7] = (unsigned long)(arg7); \
2002 _argvec[8] = (unsigned long)(arg8); \
2003 __asm__ volatile( \
2004 VALGRIND_CFI_PROLOGUE \
2005 VALGRIND_ALIGN_STACK \
2006 "subq $128,%%rsp\n\t" \
2007 "pushq 64(%%rax)\n\t" \
2008 "pushq 56(%%rax)\n\t" \
2009 "movq 48(%%rax), %%r9\n\t" \
2010 "movq 40(%%rax), %%r8\n\t" \
2011 "movq 32(%%rax), %%rcx\n\t" \
2012 "movq 24(%%rax), %%rdx\n\t" \
2013 "movq 16(%%rax), %%rsi\n\t" \
2014 "movq 8(%%rax), %%rdi\n\t" \
2015 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
2016 VALGRIND_CALL_NOREDIR_RAX \
2017 VALGRIND_RESTORE_STACK \
2018 VALGRIND_CFI_EPILOGUE \
2019 : /*out*/ "=a" (_res) \
2020 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
2021 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2022 ); \
2023 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00002024 } while (0)
2025
tom4118e0f2012-08-02 09:23:45 +00002026#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2027 arg7,arg8,arg9) \
2028 do { \
2029 volatile OrigFn _orig = (orig); \
2030 volatile unsigned long _argvec[10]; \
2031 volatile unsigned long _res; \
2032 _argvec[0] = (unsigned long)_orig.nraddr; \
2033 _argvec[1] = (unsigned long)(arg1); \
2034 _argvec[2] = (unsigned long)(arg2); \
2035 _argvec[3] = (unsigned long)(arg3); \
2036 _argvec[4] = (unsigned long)(arg4); \
2037 _argvec[5] = (unsigned long)(arg5); \
2038 _argvec[6] = (unsigned long)(arg6); \
2039 _argvec[7] = (unsigned long)(arg7); \
2040 _argvec[8] = (unsigned long)(arg8); \
2041 _argvec[9] = (unsigned long)(arg9); \
2042 __asm__ volatile( \
2043 VALGRIND_CFI_PROLOGUE \
2044 VALGRIND_ALIGN_STACK \
2045 "subq $136,%%rsp\n\t" \
2046 "pushq 72(%%rax)\n\t" \
2047 "pushq 64(%%rax)\n\t" \
2048 "pushq 56(%%rax)\n\t" \
2049 "movq 48(%%rax), %%r9\n\t" \
2050 "movq 40(%%rax), %%r8\n\t" \
2051 "movq 32(%%rax), %%rcx\n\t" \
2052 "movq 24(%%rax), %%rdx\n\t" \
2053 "movq 16(%%rax), %%rsi\n\t" \
2054 "movq 8(%%rax), %%rdi\n\t" \
2055 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
2056 VALGRIND_CALL_NOREDIR_RAX \
2057 VALGRIND_RESTORE_STACK \
2058 VALGRIND_CFI_EPILOGUE \
2059 : /*out*/ "=a" (_res) \
2060 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
2061 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2062 ); \
2063 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00002064 } while (0)
2065
tom4118e0f2012-08-02 09:23:45 +00002066#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2067 arg7,arg8,arg9,arg10) \
2068 do { \
2069 volatile OrigFn _orig = (orig); \
2070 volatile unsigned long _argvec[11]; \
2071 volatile unsigned long _res; \
2072 _argvec[0] = (unsigned long)_orig.nraddr; \
2073 _argvec[1] = (unsigned long)(arg1); \
2074 _argvec[2] = (unsigned long)(arg2); \
2075 _argvec[3] = (unsigned long)(arg3); \
2076 _argvec[4] = (unsigned long)(arg4); \
2077 _argvec[5] = (unsigned long)(arg5); \
2078 _argvec[6] = (unsigned long)(arg6); \
2079 _argvec[7] = (unsigned long)(arg7); \
2080 _argvec[8] = (unsigned long)(arg8); \
2081 _argvec[9] = (unsigned long)(arg9); \
2082 _argvec[10] = (unsigned long)(arg10); \
2083 __asm__ volatile( \
2084 VALGRIND_CFI_PROLOGUE \
2085 VALGRIND_ALIGN_STACK \
2086 "subq $128,%%rsp\n\t" \
2087 "pushq 80(%%rax)\n\t" \
2088 "pushq 72(%%rax)\n\t" \
2089 "pushq 64(%%rax)\n\t" \
2090 "pushq 56(%%rax)\n\t" \
2091 "movq 48(%%rax), %%r9\n\t" \
2092 "movq 40(%%rax), %%r8\n\t" \
2093 "movq 32(%%rax), %%rcx\n\t" \
2094 "movq 24(%%rax), %%rdx\n\t" \
2095 "movq 16(%%rax), %%rsi\n\t" \
2096 "movq 8(%%rax), %%rdi\n\t" \
2097 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
2098 VALGRIND_CALL_NOREDIR_RAX \
2099 VALGRIND_RESTORE_STACK \
2100 VALGRIND_CFI_EPILOGUE \
2101 : /*out*/ "=a" (_res) \
2102 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
2103 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2104 ); \
2105 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00002106 } while (0)
2107
tom4118e0f2012-08-02 09:23:45 +00002108#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2109 arg7,arg8,arg9,arg10,arg11) \
2110 do { \
2111 volatile OrigFn _orig = (orig); \
2112 volatile unsigned long _argvec[12]; \
2113 volatile unsigned long _res; \
2114 _argvec[0] = (unsigned long)_orig.nraddr; \
2115 _argvec[1] = (unsigned long)(arg1); \
2116 _argvec[2] = (unsigned long)(arg2); \
2117 _argvec[3] = (unsigned long)(arg3); \
2118 _argvec[4] = (unsigned long)(arg4); \
2119 _argvec[5] = (unsigned long)(arg5); \
2120 _argvec[6] = (unsigned long)(arg6); \
2121 _argvec[7] = (unsigned long)(arg7); \
2122 _argvec[8] = (unsigned long)(arg8); \
2123 _argvec[9] = (unsigned long)(arg9); \
2124 _argvec[10] = (unsigned long)(arg10); \
2125 _argvec[11] = (unsigned long)(arg11); \
2126 __asm__ volatile( \
2127 VALGRIND_CFI_PROLOGUE \
2128 VALGRIND_ALIGN_STACK \
2129 "subq $136,%%rsp\n\t" \
2130 "pushq 88(%%rax)\n\t" \
2131 "pushq 80(%%rax)\n\t" \
2132 "pushq 72(%%rax)\n\t" \
2133 "pushq 64(%%rax)\n\t" \
2134 "pushq 56(%%rax)\n\t" \
2135 "movq 48(%%rax), %%r9\n\t" \
2136 "movq 40(%%rax), %%r8\n\t" \
2137 "movq 32(%%rax), %%rcx\n\t" \
2138 "movq 24(%%rax), %%rdx\n\t" \
2139 "movq 16(%%rax), %%rsi\n\t" \
2140 "movq 8(%%rax), %%rdi\n\t" \
2141 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
2142 VALGRIND_CALL_NOREDIR_RAX \
2143 VALGRIND_RESTORE_STACK \
2144 VALGRIND_CFI_EPILOGUE \
2145 : /*out*/ "=a" (_res) \
2146 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
2147 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2148 ); \
2149 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00002150 } while (0)
2151
tom4118e0f2012-08-02 09:23:45 +00002152#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2153 arg7,arg8,arg9,arg10,arg11,arg12) \
2154 do { \
2155 volatile OrigFn _orig = (orig); \
2156 volatile unsigned long _argvec[13]; \
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 _argvec[4] = (unsigned long)(arg4); \
2163 _argvec[5] = (unsigned long)(arg5); \
2164 _argvec[6] = (unsigned long)(arg6); \
2165 _argvec[7] = (unsigned long)(arg7); \
2166 _argvec[8] = (unsigned long)(arg8); \
2167 _argvec[9] = (unsigned long)(arg9); \
2168 _argvec[10] = (unsigned long)(arg10); \
2169 _argvec[11] = (unsigned long)(arg11); \
2170 _argvec[12] = (unsigned long)(arg12); \
2171 __asm__ volatile( \
2172 VALGRIND_CFI_PROLOGUE \
2173 VALGRIND_ALIGN_STACK \
2174 "subq $128,%%rsp\n\t" \
2175 "pushq 96(%%rax)\n\t" \
2176 "pushq 88(%%rax)\n\t" \
2177 "pushq 80(%%rax)\n\t" \
2178 "pushq 72(%%rax)\n\t" \
2179 "pushq 64(%%rax)\n\t" \
2180 "pushq 56(%%rax)\n\t" \
2181 "movq 48(%%rax), %%r9\n\t" \
2182 "movq 40(%%rax), %%r8\n\t" \
2183 "movq 32(%%rax), %%rcx\n\t" \
2184 "movq 24(%%rax), %%rdx\n\t" \
2185 "movq 16(%%rax), %%rsi\n\t" \
2186 "movq 8(%%rax), %%rdi\n\t" \
2187 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
2188 VALGRIND_CALL_NOREDIR_RAX \
2189 VALGRIND_RESTORE_STACK \
2190 VALGRIND_CFI_EPILOGUE \
2191 : /*out*/ "=a" (_res) \
2192 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
2193 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2194 ); \
2195 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00002196 } while (0)
2197
sewardj8eb8bab2015-07-21 14:44:28 +00002198#endif /* PLAT_amd64_linux || PLAT_amd64_darwin || PLAT_amd64_solaris */
sewardj0ec07f32006-01-12 12:32:32 +00002199
sewardjf5c1a7f2006-10-17 01:32:48 +00002200/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002201
sewardjf5c1a7f2006-10-17 01:32:48 +00002202#if defined(PLAT_ppc32_linux)
sewardj0ec07f32006-01-12 12:32:32 +00002203
sewardjead61df2006-03-12 13:39:15 +00002204/* This is useful for finding out about the on-stack stuff:
2205
2206 extern int f9 ( int,int,int,int,int,int,int,int,int );
2207 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
2208 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
2209 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
2210
2211 int g9 ( void ) {
2212 return f9(11,22,33,44,55,66,77,88,99);
2213 }
2214 int g10 ( void ) {
2215 return f10(11,22,33,44,55,66,77,88,99,110);
2216 }
2217 int g11 ( void ) {
2218 return f11(11,22,33,44,55,66,77,88,99,110,121);
2219 }
2220 int g12 ( void ) {
2221 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
2222 }
2223*/
2224
sewardj0ec07f32006-01-12 12:32:32 +00002225/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2226
2227/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00002228#define __CALLER_SAVED_REGS \
2229 "lr", "ctr", "xer", \
2230 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2231 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2232 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00002233
tom4118e0f2012-08-02 09:23:45 +00002234/* Macros to save and align the stack before making a function
2235 call and restore it afterwards as gcc may not keep the stack
2236 pointer aligned if it doesn't realise calls are being made
2237 to other functions. */
2238
2239#define VALGRIND_ALIGN_STACK \
2240 "mr 28,1\n\t" \
2241 "rlwinm 1,1,0,0,27\n\t"
2242#define VALGRIND_RESTORE_STACK \
2243 "mr 1,28\n\t"
2244
sewardjead61df2006-03-12 13:39:15 +00002245/* These CALL_FN_ macros assume that on ppc32-linux,
2246 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00002247
sewardj38de0992006-01-20 16:46:34 +00002248#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00002249 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002250 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00002251 volatile unsigned long _argvec[1]; \
2252 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002253 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00002254 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002255 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002256 "mr 11,%1\n\t" \
2257 "lwz 11,0(11)\n\t" /* target->r11 */ \
2258 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002259 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002260 "mr %0,3" \
2261 : /*out*/ "=r" (_res) \
2262 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002263 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj0ec07f32006-01-12 12:32:32 +00002264 ); \
2265 lval = (__typeof__(lval)) _res; \
2266 } while (0)
2267
sewardj38de0992006-01-20 16:46:34 +00002268#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00002269 do { \
sewardj38de0992006-01-20 16:46:34 +00002270 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00002271 volatile unsigned long _argvec[2]; \
2272 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00002273 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00002274 _argvec[1] = (unsigned long)arg1; \
2275 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002276 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002277 "mr 11,%1\n\t" \
2278 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2279 "lwz 11,0(11)\n\t" /* target->r11 */ \
2280 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002281 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002282 "mr %0,3" \
2283 : /*out*/ "=r" (_res) \
2284 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002285 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj0ec07f32006-01-12 12:32:32 +00002286 ); \
2287 lval = (__typeof__(lval)) _res; \
2288 } while (0)
2289
sewardj38de0992006-01-20 16:46:34 +00002290#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00002291 do { \
sewardj38de0992006-01-20 16:46:34 +00002292 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00002293 volatile unsigned long _argvec[3]; \
2294 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00002295 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00002296 _argvec[1] = (unsigned long)arg1; \
2297 _argvec[2] = (unsigned long)arg2; \
2298 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002299 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002300 "mr 11,%1\n\t" \
2301 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2302 "lwz 4,8(11)\n\t" \
2303 "lwz 11,0(11)\n\t" /* target->r11 */ \
2304 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002305 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00002306 "mr %0,3" \
2307 : /*out*/ "=r" (_res) \
2308 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002309 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj0ec07f32006-01-12 12:32:32 +00002310 ); \
2311 lval = (__typeof__(lval)) _res; \
2312 } while (0)
2313
sewardjead61df2006-03-12 13:39:15 +00002314#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2315 do { \
2316 volatile OrigFn _orig = (orig); \
2317 volatile unsigned long _argvec[4]; \
2318 volatile unsigned long _res; \
2319 _argvec[0] = (unsigned long)_orig.nraddr; \
2320 _argvec[1] = (unsigned long)arg1; \
2321 _argvec[2] = (unsigned long)arg2; \
2322 _argvec[3] = (unsigned long)arg3; \
2323 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002324 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002325 "mr 11,%1\n\t" \
2326 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2327 "lwz 4,8(11)\n\t" \
2328 "lwz 5,12(11)\n\t" \
2329 "lwz 11,0(11)\n\t" /* target->r11 */ \
2330 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002331 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002332 "mr %0,3" \
2333 : /*out*/ "=r" (_res) \
2334 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002335 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002336 ); \
2337 lval = (__typeof__(lval)) _res; \
2338 } while (0)
2339
2340#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2341 do { \
2342 volatile OrigFn _orig = (orig); \
2343 volatile unsigned long _argvec[5]; \
2344 volatile unsigned long _res; \
2345 _argvec[0] = (unsigned long)_orig.nraddr; \
2346 _argvec[1] = (unsigned long)arg1; \
2347 _argvec[2] = (unsigned long)arg2; \
2348 _argvec[3] = (unsigned long)arg3; \
2349 _argvec[4] = (unsigned long)arg4; \
2350 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002351 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002352 "mr 11,%1\n\t" \
2353 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2354 "lwz 4,8(11)\n\t" \
2355 "lwz 5,12(11)\n\t" \
2356 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2357 "lwz 11,0(11)\n\t" /* target->r11 */ \
2358 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002359 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002360 "mr %0,3" \
2361 : /*out*/ "=r" (_res) \
2362 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002363 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002364 ); \
2365 lval = (__typeof__(lval)) _res; \
2366 } while (0)
2367
2368#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2369 do { \
2370 volatile OrigFn _orig = (orig); \
2371 volatile unsigned long _argvec[6]; \
2372 volatile unsigned long _res; \
2373 _argvec[0] = (unsigned long)_orig.nraddr; \
2374 _argvec[1] = (unsigned long)arg1; \
2375 _argvec[2] = (unsigned long)arg2; \
2376 _argvec[3] = (unsigned long)arg3; \
2377 _argvec[4] = (unsigned long)arg4; \
2378 _argvec[5] = (unsigned long)arg5; \
2379 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002380 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002381 "mr 11,%1\n\t" \
2382 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2383 "lwz 4,8(11)\n\t" \
2384 "lwz 5,12(11)\n\t" \
2385 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2386 "lwz 7,20(11)\n\t" \
2387 "lwz 11,0(11)\n\t" /* target->r11 */ \
2388 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002389 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002390 "mr %0,3" \
2391 : /*out*/ "=r" (_res) \
2392 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002393 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002394 ); \
2395 lval = (__typeof__(lval)) _res; \
2396 } while (0)
2397
2398#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2399 do { \
2400 volatile OrigFn _orig = (orig); \
2401 volatile unsigned long _argvec[7]; \
2402 volatile unsigned long _res; \
2403 _argvec[0] = (unsigned long)_orig.nraddr; \
2404 _argvec[1] = (unsigned long)arg1; \
2405 _argvec[2] = (unsigned long)arg2; \
2406 _argvec[3] = (unsigned long)arg3; \
2407 _argvec[4] = (unsigned long)arg4; \
2408 _argvec[5] = (unsigned long)arg5; \
2409 _argvec[6] = (unsigned long)arg6; \
2410 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002411 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002412 "mr 11,%1\n\t" \
2413 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2414 "lwz 4,8(11)\n\t" \
2415 "lwz 5,12(11)\n\t" \
2416 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2417 "lwz 7,20(11)\n\t" \
2418 "lwz 8,24(11)\n\t" \
2419 "lwz 11,0(11)\n\t" /* target->r11 */ \
2420 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002421 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002422 "mr %0,3" \
2423 : /*out*/ "=r" (_res) \
2424 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002425 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002426 ); \
2427 lval = (__typeof__(lval)) _res; \
2428 } while (0)
2429
2430#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2431 arg7) \
2432 do { \
2433 volatile OrigFn _orig = (orig); \
2434 volatile unsigned long _argvec[8]; \
2435 volatile unsigned long _res; \
2436 _argvec[0] = (unsigned long)_orig.nraddr; \
2437 _argvec[1] = (unsigned long)arg1; \
2438 _argvec[2] = (unsigned long)arg2; \
2439 _argvec[3] = (unsigned long)arg3; \
2440 _argvec[4] = (unsigned long)arg4; \
2441 _argvec[5] = (unsigned long)arg5; \
2442 _argvec[6] = (unsigned long)arg6; \
2443 _argvec[7] = (unsigned long)arg7; \
2444 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002445 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002446 "mr 11,%1\n\t" \
2447 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2448 "lwz 4,8(11)\n\t" \
2449 "lwz 5,12(11)\n\t" \
2450 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2451 "lwz 7,20(11)\n\t" \
2452 "lwz 8,24(11)\n\t" \
2453 "lwz 9,28(11)\n\t" \
2454 "lwz 11,0(11)\n\t" /* target->r11 */ \
2455 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002456 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002457 "mr %0,3" \
2458 : /*out*/ "=r" (_res) \
2459 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002460 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002461 ); \
2462 lval = (__typeof__(lval)) _res; \
2463 } while (0)
2464
2465#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2466 arg7,arg8) \
2467 do { \
2468 volatile OrigFn _orig = (orig); \
2469 volatile unsigned long _argvec[9]; \
2470 volatile unsigned long _res; \
2471 _argvec[0] = (unsigned long)_orig.nraddr; \
2472 _argvec[1] = (unsigned long)arg1; \
2473 _argvec[2] = (unsigned long)arg2; \
2474 _argvec[3] = (unsigned long)arg3; \
2475 _argvec[4] = (unsigned long)arg4; \
2476 _argvec[5] = (unsigned long)arg5; \
2477 _argvec[6] = (unsigned long)arg6; \
2478 _argvec[7] = (unsigned long)arg7; \
2479 _argvec[8] = (unsigned long)arg8; \
2480 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002481 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002482 "mr 11,%1\n\t" \
2483 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2484 "lwz 4,8(11)\n\t" \
2485 "lwz 5,12(11)\n\t" \
2486 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2487 "lwz 7,20(11)\n\t" \
2488 "lwz 8,24(11)\n\t" \
2489 "lwz 9,28(11)\n\t" \
2490 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2491 "lwz 11,0(11)\n\t" /* target->r11 */ \
2492 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002493 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002494 "mr %0,3" \
2495 : /*out*/ "=r" (_res) \
2496 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002497 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002498 ); \
2499 lval = (__typeof__(lval)) _res; \
2500 } while (0)
2501
2502#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2503 arg7,arg8,arg9) \
2504 do { \
2505 volatile OrigFn _orig = (orig); \
2506 volatile unsigned long _argvec[10]; \
2507 volatile unsigned long _res; \
2508 _argvec[0] = (unsigned long)_orig.nraddr; \
2509 _argvec[1] = (unsigned long)arg1; \
2510 _argvec[2] = (unsigned long)arg2; \
2511 _argvec[3] = (unsigned long)arg3; \
2512 _argvec[4] = (unsigned long)arg4; \
2513 _argvec[5] = (unsigned long)arg5; \
2514 _argvec[6] = (unsigned long)arg6; \
2515 _argvec[7] = (unsigned long)arg7; \
2516 _argvec[8] = (unsigned long)arg8; \
2517 _argvec[9] = (unsigned long)arg9; \
2518 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002519 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002520 "mr 11,%1\n\t" \
2521 "addi 1,1,-16\n\t" \
2522 /* arg9 */ \
2523 "lwz 3,36(11)\n\t" \
2524 "stw 3,8(1)\n\t" \
2525 /* args1-8 */ \
2526 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2527 "lwz 4,8(11)\n\t" \
2528 "lwz 5,12(11)\n\t" \
2529 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2530 "lwz 7,20(11)\n\t" \
2531 "lwz 8,24(11)\n\t" \
2532 "lwz 9,28(11)\n\t" \
2533 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2534 "lwz 11,0(11)\n\t" /* target->r11 */ \
2535 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002536 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002537 "mr %0,3" \
2538 : /*out*/ "=r" (_res) \
2539 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002540 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002541 ); \
2542 lval = (__typeof__(lval)) _res; \
2543 } while (0)
2544
2545#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2546 arg7,arg8,arg9,arg10) \
2547 do { \
2548 volatile OrigFn _orig = (orig); \
2549 volatile unsigned long _argvec[11]; \
2550 volatile unsigned long _res; \
2551 _argvec[0] = (unsigned long)_orig.nraddr; \
2552 _argvec[1] = (unsigned long)arg1; \
2553 _argvec[2] = (unsigned long)arg2; \
2554 _argvec[3] = (unsigned long)arg3; \
2555 _argvec[4] = (unsigned long)arg4; \
2556 _argvec[5] = (unsigned long)arg5; \
2557 _argvec[6] = (unsigned long)arg6; \
2558 _argvec[7] = (unsigned long)arg7; \
2559 _argvec[8] = (unsigned long)arg8; \
2560 _argvec[9] = (unsigned long)arg9; \
2561 _argvec[10] = (unsigned long)arg10; \
2562 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002563 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002564 "mr 11,%1\n\t" \
2565 "addi 1,1,-16\n\t" \
2566 /* arg10 */ \
2567 "lwz 3,40(11)\n\t" \
2568 "stw 3,12(1)\n\t" \
2569 /* arg9 */ \
2570 "lwz 3,36(11)\n\t" \
2571 "stw 3,8(1)\n\t" \
2572 /* args1-8 */ \
2573 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2574 "lwz 4,8(11)\n\t" \
2575 "lwz 5,12(11)\n\t" \
2576 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2577 "lwz 7,20(11)\n\t" \
2578 "lwz 8,24(11)\n\t" \
2579 "lwz 9,28(11)\n\t" \
2580 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2581 "lwz 11,0(11)\n\t" /* target->r11 */ \
2582 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002583 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002584 "mr %0,3" \
2585 : /*out*/ "=r" (_res) \
2586 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002587 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002588 ); \
2589 lval = (__typeof__(lval)) _res; \
2590 } while (0)
2591
2592#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2593 arg7,arg8,arg9,arg10,arg11) \
2594 do { \
2595 volatile OrigFn _orig = (orig); \
2596 volatile unsigned long _argvec[12]; \
2597 volatile unsigned long _res; \
2598 _argvec[0] = (unsigned long)_orig.nraddr; \
2599 _argvec[1] = (unsigned long)arg1; \
2600 _argvec[2] = (unsigned long)arg2; \
2601 _argvec[3] = (unsigned long)arg3; \
2602 _argvec[4] = (unsigned long)arg4; \
2603 _argvec[5] = (unsigned long)arg5; \
2604 _argvec[6] = (unsigned long)arg6; \
2605 _argvec[7] = (unsigned long)arg7; \
2606 _argvec[8] = (unsigned long)arg8; \
2607 _argvec[9] = (unsigned long)arg9; \
2608 _argvec[10] = (unsigned long)arg10; \
2609 _argvec[11] = (unsigned long)arg11; \
2610 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002611 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002612 "mr 11,%1\n\t" \
2613 "addi 1,1,-32\n\t" \
2614 /* arg11 */ \
2615 "lwz 3,44(11)\n\t" \
2616 "stw 3,16(1)\n\t" \
2617 /* arg10 */ \
2618 "lwz 3,40(11)\n\t" \
2619 "stw 3,12(1)\n\t" \
2620 /* arg9 */ \
2621 "lwz 3,36(11)\n\t" \
2622 "stw 3,8(1)\n\t" \
2623 /* args1-8 */ \
2624 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2625 "lwz 4,8(11)\n\t" \
2626 "lwz 5,12(11)\n\t" \
2627 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2628 "lwz 7,20(11)\n\t" \
2629 "lwz 8,24(11)\n\t" \
2630 "lwz 9,28(11)\n\t" \
2631 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2632 "lwz 11,0(11)\n\t" /* target->r11 */ \
2633 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002634 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002635 "mr %0,3" \
2636 : /*out*/ "=r" (_res) \
2637 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002638 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002639 ); \
2640 lval = (__typeof__(lval)) _res; \
2641 } while (0)
2642
2643#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2644 arg7,arg8,arg9,arg10,arg11,arg12) \
2645 do { \
2646 volatile OrigFn _orig = (orig); \
2647 volatile unsigned long _argvec[13]; \
2648 volatile unsigned long _res; \
2649 _argvec[0] = (unsigned long)_orig.nraddr; \
2650 _argvec[1] = (unsigned long)arg1; \
2651 _argvec[2] = (unsigned long)arg2; \
2652 _argvec[3] = (unsigned long)arg3; \
2653 _argvec[4] = (unsigned long)arg4; \
2654 _argvec[5] = (unsigned long)arg5; \
2655 _argvec[6] = (unsigned long)arg6; \
2656 _argvec[7] = (unsigned long)arg7; \
2657 _argvec[8] = (unsigned long)arg8; \
2658 _argvec[9] = (unsigned long)arg9; \
2659 _argvec[10] = (unsigned long)arg10; \
2660 _argvec[11] = (unsigned long)arg11; \
2661 _argvec[12] = (unsigned long)arg12; \
2662 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002663 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002664 "mr 11,%1\n\t" \
2665 "addi 1,1,-32\n\t" \
2666 /* arg12 */ \
2667 "lwz 3,48(11)\n\t" \
2668 "stw 3,20(1)\n\t" \
2669 /* arg11 */ \
2670 "lwz 3,44(11)\n\t" \
2671 "stw 3,16(1)\n\t" \
2672 /* arg10 */ \
2673 "lwz 3,40(11)\n\t" \
2674 "stw 3,12(1)\n\t" \
2675 /* arg9 */ \
2676 "lwz 3,36(11)\n\t" \
2677 "stw 3,8(1)\n\t" \
2678 /* args1-8 */ \
2679 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2680 "lwz 4,8(11)\n\t" \
2681 "lwz 5,12(11)\n\t" \
2682 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2683 "lwz 7,20(11)\n\t" \
2684 "lwz 8,24(11)\n\t" \
2685 "lwz 9,28(11)\n\t" \
2686 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2687 "lwz 11,0(11)\n\t" /* target->r11 */ \
2688 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002689 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002690 "mr %0,3" \
2691 : /*out*/ "=r" (_res) \
2692 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002693 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002694 ); \
2695 lval = (__typeof__(lval)) _res; \
2696 } while (0)
2697
sewardjf5c1a7f2006-10-17 01:32:48 +00002698#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +00002699
sewardjf5c1a7f2006-10-17 01:32:48 +00002700/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002701
carllcae0cc22014-08-07 23:17:29 +00002702#if defined(PLAT_ppc64be_linux)
sewardj9734b202006-01-17 01:49:37 +00002703
2704/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2705
2706/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00002707#define __CALLER_SAVED_REGS \
2708 "lr", "ctr", "xer", \
2709 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2710 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2711 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00002712
tom4118e0f2012-08-02 09:23:45 +00002713/* Macros to save and align the stack before making a function
2714 call and restore it afterwards as gcc may not keep the stack
2715 pointer aligned if it doesn't realise calls are being made
2716 to other functions. */
2717
2718#define VALGRIND_ALIGN_STACK \
2719 "mr 28,1\n\t" \
2720 "rldicr 1,1,0,59\n\t"
2721#define VALGRIND_RESTORE_STACK \
2722 "mr 1,28\n\t"
2723
sewardj9734b202006-01-17 01:49:37 +00002724/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2725 long) == 8. */
2726
sewardjd68ac3e2006-01-20 14:31:57 +00002727#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00002728 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002729 volatile OrigFn _orig = (orig); \
2730 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00002731 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002732 /* _argvec[0] holds current r2 across the call */ \
2733 _argvec[1] = (unsigned long)_orig.r2; \
2734 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00002735 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002736 VALGRIND_ALIGN_STACK \
sewardj9734b202006-01-17 01:49:37 +00002737 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002738 "std 2,-16(11)\n\t" /* save tocptr */ \
2739 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2740 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002741 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2742 "mr 11,%1\n\t" \
2743 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002744 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2745 VALGRIND_RESTORE_STACK \
sewardj9734b202006-01-17 01:49:37 +00002746 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002747 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002748 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj9734b202006-01-17 01:49:37 +00002749 ); \
2750 lval = (__typeof__(lval)) _res; \
2751 } while (0)
2752
sewardjd68ac3e2006-01-20 14:31:57 +00002753#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00002754 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002755 volatile OrigFn _orig = (orig); \
2756 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00002757 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002758 /* _argvec[0] holds current r2 across the call */ \
2759 _argvec[1] = (unsigned long)_orig.r2; \
2760 _argvec[2] = (unsigned long)_orig.nraddr; \
2761 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00002762 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002763 VALGRIND_ALIGN_STACK \
sewardj9734b202006-01-17 01:49:37 +00002764 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002765 "std 2,-16(11)\n\t" /* save tocptr */ \
2766 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2767 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2768 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002769 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2770 "mr 11,%1\n\t" \
2771 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002772 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2773 VALGRIND_RESTORE_STACK \
sewardj9734b202006-01-17 01:49:37 +00002774 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002775 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002776 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj9734b202006-01-17 01:49:37 +00002777 ); \
2778 lval = (__typeof__(lval)) _res; \
2779 } while (0)
2780
sewardjd68ac3e2006-01-20 14:31:57 +00002781#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00002782 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002783 volatile OrigFn _orig = (orig); \
2784 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00002785 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002786 /* _argvec[0] holds current r2 across the call */ \
2787 _argvec[1] = (unsigned long)_orig.r2; \
2788 _argvec[2] = (unsigned long)_orig.nraddr; \
2789 _argvec[2+1] = (unsigned long)arg1; \
2790 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00002791 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002792 VALGRIND_ALIGN_STACK \
sewardj9734b202006-01-17 01:49:37 +00002793 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002794 "std 2,-16(11)\n\t" /* save tocptr */ \
2795 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2796 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00002797 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00002798 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002799 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2800 "mr 11,%1\n\t" \
2801 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002802 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2803 VALGRIND_RESTORE_STACK \
sewardj9734b202006-01-17 01:49:37 +00002804 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002805 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002806 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj9734b202006-01-17 01:49:37 +00002807 ); \
2808 lval = (__typeof__(lval)) _res; \
2809 } while (0)
2810
sewardjcd636392006-03-12 16:48:14 +00002811#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2812 do { \
2813 volatile OrigFn _orig = (orig); \
2814 volatile unsigned long _argvec[3+3]; \
2815 volatile unsigned long _res; \
2816 /* _argvec[0] holds current r2 across the call */ \
2817 _argvec[1] = (unsigned long)_orig.r2; \
2818 _argvec[2] = (unsigned long)_orig.nraddr; \
2819 _argvec[2+1] = (unsigned long)arg1; \
2820 _argvec[2+2] = (unsigned long)arg2; \
2821 _argvec[2+3] = (unsigned long)arg3; \
2822 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002823 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002824 "mr 11,%1\n\t" \
2825 "std 2,-16(11)\n\t" /* save tocptr */ \
2826 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2827 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2828 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2829 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2830 "ld 11, 0(11)\n\t" /* target->r11 */ \
2831 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2832 "mr 11,%1\n\t" \
2833 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002834 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2835 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002836 : /*out*/ "=r" (_res) \
2837 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002838 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002839 ); \
2840 lval = (__typeof__(lval)) _res; \
2841 } while (0)
2842
2843#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2844 do { \
2845 volatile OrigFn _orig = (orig); \
2846 volatile unsigned long _argvec[3+4]; \
2847 volatile unsigned long _res; \
2848 /* _argvec[0] holds current r2 across the call */ \
2849 _argvec[1] = (unsigned long)_orig.r2; \
2850 _argvec[2] = (unsigned long)_orig.nraddr; \
2851 _argvec[2+1] = (unsigned long)arg1; \
2852 _argvec[2+2] = (unsigned long)arg2; \
2853 _argvec[2+3] = (unsigned long)arg3; \
2854 _argvec[2+4] = (unsigned long)arg4; \
2855 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002856 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002857 "mr 11,%1\n\t" \
2858 "std 2,-16(11)\n\t" /* save tocptr */ \
2859 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2860 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2861 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2862 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2863 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2864 "ld 11, 0(11)\n\t" /* target->r11 */ \
2865 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2866 "mr 11,%1\n\t" \
2867 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002868 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2869 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002870 : /*out*/ "=r" (_res) \
2871 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002872 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002873 ); \
2874 lval = (__typeof__(lval)) _res; \
2875 } while (0)
2876
2877#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2878 do { \
2879 volatile OrigFn _orig = (orig); \
2880 volatile unsigned long _argvec[3+5]; \
2881 volatile unsigned long _res; \
2882 /* _argvec[0] holds current r2 across the call */ \
2883 _argvec[1] = (unsigned long)_orig.r2; \
2884 _argvec[2] = (unsigned long)_orig.nraddr; \
2885 _argvec[2+1] = (unsigned long)arg1; \
2886 _argvec[2+2] = (unsigned long)arg2; \
2887 _argvec[2+3] = (unsigned long)arg3; \
2888 _argvec[2+4] = (unsigned long)arg4; \
2889 _argvec[2+5] = (unsigned long)arg5; \
2890 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002891 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002892 "mr 11,%1\n\t" \
2893 "std 2,-16(11)\n\t" /* save tocptr */ \
2894 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2895 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2896 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2897 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2898 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2899 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2900 "ld 11, 0(11)\n\t" /* target->r11 */ \
2901 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2902 "mr 11,%1\n\t" \
2903 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002904 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2905 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002906 : /*out*/ "=r" (_res) \
2907 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002908 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002909 ); \
2910 lval = (__typeof__(lval)) _res; \
2911 } while (0)
2912
2913#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2914 do { \
2915 volatile OrigFn _orig = (orig); \
2916 volatile unsigned long _argvec[3+6]; \
2917 volatile unsigned long _res; \
2918 /* _argvec[0] holds current r2 across the call */ \
2919 _argvec[1] = (unsigned long)_orig.r2; \
2920 _argvec[2] = (unsigned long)_orig.nraddr; \
2921 _argvec[2+1] = (unsigned long)arg1; \
2922 _argvec[2+2] = (unsigned long)arg2; \
2923 _argvec[2+3] = (unsigned long)arg3; \
2924 _argvec[2+4] = (unsigned long)arg4; \
2925 _argvec[2+5] = (unsigned long)arg5; \
2926 _argvec[2+6] = (unsigned long)arg6; \
2927 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002928 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002929 "mr 11,%1\n\t" \
2930 "std 2,-16(11)\n\t" /* save tocptr */ \
2931 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2932 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2933 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2934 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2935 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2936 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2937 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2938 "ld 11, 0(11)\n\t" /* target->r11 */ \
2939 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2940 "mr 11,%1\n\t" \
2941 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002942 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2943 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002944 : /*out*/ "=r" (_res) \
2945 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002946 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002947 ); \
2948 lval = (__typeof__(lval)) _res; \
2949 } while (0)
2950
2951#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2952 arg7) \
2953 do { \
2954 volatile OrigFn _orig = (orig); \
2955 volatile unsigned long _argvec[3+7]; \
2956 volatile unsigned long _res; \
2957 /* _argvec[0] holds current r2 across the call */ \
2958 _argvec[1] = (unsigned long)_orig.r2; \
2959 _argvec[2] = (unsigned long)_orig.nraddr; \
2960 _argvec[2+1] = (unsigned long)arg1; \
2961 _argvec[2+2] = (unsigned long)arg2; \
2962 _argvec[2+3] = (unsigned long)arg3; \
2963 _argvec[2+4] = (unsigned long)arg4; \
2964 _argvec[2+5] = (unsigned long)arg5; \
2965 _argvec[2+6] = (unsigned long)arg6; \
2966 _argvec[2+7] = (unsigned long)arg7; \
2967 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002968 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002969 "mr 11,%1\n\t" \
2970 "std 2,-16(11)\n\t" /* save tocptr */ \
2971 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2972 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2973 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2974 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2975 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2976 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2977 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2978 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2979 "ld 11, 0(11)\n\t" /* target->r11 */ \
2980 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2981 "mr 11,%1\n\t" \
2982 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002983 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2984 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002985 : /*out*/ "=r" (_res) \
2986 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002987 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002988 ); \
2989 lval = (__typeof__(lval)) _res; \
2990 } while (0)
2991
2992#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2993 arg7,arg8) \
2994 do { \
2995 volatile OrigFn _orig = (orig); \
2996 volatile unsigned long _argvec[3+8]; \
2997 volatile unsigned long _res; \
2998 /* _argvec[0] holds current r2 across the call */ \
2999 _argvec[1] = (unsigned long)_orig.r2; \
3000 _argvec[2] = (unsigned long)_orig.nraddr; \
3001 _argvec[2+1] = (unsigned long)arg1; \
3002 _argvec[2+2] = (unsigned long)arg2; \
3003 _argvec[2+3] = (unsigned long)arg3; \
3004 _argvec[2+4] = (unsigned long)arg4; \
3005 _argvec[2+5] = (unsigned long)arg5; \
3006 _argvec[2+6] = (unsigned long)arg6; \
3007 _argvec[2+7] = (unsigned long)arg7; \
3008 _argvec[2+8] = (unsigned long)arg8; \
3009 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003010 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00003011 "mr 11,%1\n\t" \
3012 "std 2,-16(11)\n\t" /* save tocptr */ \
3013 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3014 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3015 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3016 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3017 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3018 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3019 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3020 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3021 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3022 "ld 11, 0(11)\n\t" /* target->r11 */ \
3023 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3024 "mr 11,%1\n\t" \
3025 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00003026 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3027 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00003028 : /*out*/ "=r" (_res) \
3029 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00003030 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00003031 ); \
3032 lval = (__typeof__(lval)) _res; \
3033 } while (0)
3034
3035#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3036 arg7,arg8,arg9) \
3037 do { \
3038 volatile OrigFn _orig = (orig); \
3039 volatile unsigned long _argvec[3+9]; \
3040 volatile unsigned long _res; \
3041 /* _argvec[0] holds current r2 across the call */ \
3042 _argvec[1] = (unsigned long)_orig.r2; \
3043 _argvec[2] = (unsigned long)_orig.nraddr; \
3044 _argvec[2+1] = (unsigned long)arg1; \
3045 _argvec[2+2] = (unsigned long)arg2; \
3046 _argvec[2+3] = (unsigned long)arg3; \
3047 _argvec[2+4] = (unsigned long)arg4; \
3048 _argvec[2+5] = (unsigned long)arg5; \
3049 _argvec[2+6] = (unsigned long)arg6; \
3050 _argvec[2+7] = (unsigned long)arg7; \
3051 _argvec[2+8] = (unsigned long)arg8; \
3052 _argvec[2+9] = (unsigned long)arg9; \
3053 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003054 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00003055 "mr 11,%1\n\t" \
3056 "std 2,-16(11)\n\t" /* save tocptr */ \
3057 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3058 "addi 1,1,-128\n\t" /* expand stack frame */ \
3059 /* arg9 */ \
3060 "ld 3,72(11)\n\t" \
3061 "std 3,112(1)\n\t" \
3062 /* args1-8 */ \
3063 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3064 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3065 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3066 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3067 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3068 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3069 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3070 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3071 "ld 11, 0(11)\n\t" /* target->r11 */ \
3072 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3073 "mr 11,%1\n\t" \
3074 "mr %0,3\n\t" \
3075 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00003076 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00003077 : /*out*/ "=r" (_res) \
3078 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00003079 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00003080 ); \
3081 lval = (__typeof__(lval)) _res; \
3082 } while (0)
3083
3084#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3085 arg7,arg8,arg9,arg10) \
3086 do { \
3087 volatile OrigFn _orig = (orig); \
3088 volatile unsigned long _argvec[3+10]; \
3089 volatile unsigned long _res; \
3090 /* _argvec[0] holds current r2 across the call */ \
3091 _argvec[1] = (unsigned long)_orig.r2; \
3092 _argvec[2] = (unsigned long)_orig.nraddr; \
3093 _argvec[2+1] = (unsigned long)arg1; \
3094 _argvec[2+2] = (unsigned long)arg2; \
3095 _argvec[2+3] = (unsigned long)arg3; \
3096 _argvec[2+4] = (unsigned long)arg4; \
3097 _argvec[2+5] = (unsigned long)arg5; \
3098 _argvec[2+6] = (unsigned long)arg6; \
3099 _argvec[2+7] = (unsigned long)arg7; \
3100 _argvec[2+8] = (unsigned long)arg8; \
3101 _argvec[2+9] = (unsigned long)arg9; \
3102 _argvec[2+10] = (unsigned long)arg10; \
3103 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003104 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00003105 "mr 11,%1\n\t" \
3106 "std 2,-16(11)\n\t" /* save tocptr */ \
3107 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3108 "addi 1,1,-128\n\t" /* expand stack frame */ \
3109 /* arg10 */ \
3110 "ld 3,80(11)\n\t" \
3111 "std 3,120(1)\n\t" \
3112 /* arg9 */ \
3113 "ld 3,72(11)\n\t" \
3114 "std 3,112(1)\n\t" \
3115 /* args1-8 */ \
3116 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3117 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3118 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3119 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3120 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3121 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3122 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3123 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3124 "ld 11, 0(11)\n\t" /* target->r11 */ \
3125 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3126 "mr 11,%1\n\t" \
3127 "mr %0,3\n\t" \
3128 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00003129 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00003130 : /*out*/ "=r" (_res) \
3131 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00003132 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00003133 ); \
3134 lval = (__typeof__(lval)) _res; \
3135 } while (0)
3136
3137#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3138 arg7,arg8,arg9,arg10,arg11) \
3139 do { \
3140 volatile OrigFn _orig = (orig); \
3141 volatile unsigned long _argvec[3+11]; \
3142 volatile unsigned long _res; \
3143 /* _argvec[0] holds current r2 across the call */ \
3144 _argvec[1] = (unsigned long)_orig.r2; \
3145 _argvec[2] = (unsigned long)_orig.nraddr; \
3146 _argvec[2+1] = (unsigned long)arg1; \
3147 _argvec[2+2] = (unsigned long)arg2; \
3148 _argvec[2+3] = (unsigned long)arg3; \
3149 _argvec[2+4] = (unsigned long)arg4; \
3150 _argvec[2+5] = (unsigned long)arg5; \
3151 _argvec[2+6] = (unsigned long)arg6; \
3152 _argvec[2+7] = (unsigned long)arg7; \
3153 _argvec[2+8] = (unsigned long)arg8; \
3154 _argvec[2+9] = (unsigned long)arg9; \
3155 _argvec[2+10] = (unsigned long)arg10; \
3156 _argvec[2+11] = (unsigned long)arg11; \
3157 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003158 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00003159 "mr 11,%1\n\t" \
3160 "std 2,-16(11)\n\t" /* save tocptr */ \
3161 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3162 "addi 1,1,-144\n\t" /* expand stack frame */ \
3163 /* arg11 */ \
3164 "ld 3,88(11)\n\t" \
3165 "std 3,128(1)\n\t" \
3166 /* arg10 */ \
3167 "ld 3,80(11)\n\t" \
3168 "std 3,120(1)\n\t" \
3169 /* arg9 */ \
3170 "ld 3,72(11)\n\t" \
3171 "std 3,112(1)\n\t" \
3172 /* args1-8 */ \
3173 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3174 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3175 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3176 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3177 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3178 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3179 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3180 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3181 "ld 11, 0(11)\n\t" /* target->r11 */ \
3182 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3183 "mr 11,%1\n\t" \
3184 "mr %0,3\n\t" \
3185 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00003186 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00003187 : /*out*/ "=r" (_res) \
3188 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00003189 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00003190 ); \
3191 lval = (__typeof__(lval)) _res; \
3192 } while (0)
3193
3194#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3195 arg7,arg8,arg9,arg10,arg11,arg12) \
3196 do { \
3197 volatile OrigFn _orig = (orig); \
3198 volatile unsigned long _argvec[3+12]; \
3199 volatile unsigned long _res; \
3200 /* _argvec[0] holds current r2 across the call */ \
3201 _argvec[1] = (unsigned long)_orig.r2; \
3202 _argvec[2] = (unsigned long)_orig.nraddr; \
3203 _argvec[2+1] = (unsigned long)arg1; \
3204 _argvec[2+2] = (unsigned long)arg2; \
3205 _argvec[2+3] = (unsigned long)arg3; \
3206 _argvec[2+4] = (unsigned long)arg4; \
3207 _argvec[2+5] = (unsigned long)arg5; \
3208 _argvec[2+6] = (unsigned long)arg6; \
3209 _argvec[2+7] = (unsigned long)arg7; \
3210 _argvec[2+8] = (unsigned long)arg8; \
3211 _argvec[2+9] = (unsigned long)arg9; \
3212 _argvec[2+10] = (unsigned long)arg10; \
3213 _argvec[2+11] = (unsigned long)arg11; \
3214 _argvec[2+12] = (unsigned long)arg12; \
3215 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003216 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00003217 "mr 11,%1\n\t" \
3218 "std 2,-16(11)\n\t" /* save tocptr */ \
3219 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3220 "addi 1,1,-144\n\t" /* expand stack frame */ \
3221 /* arg12 */ \
3222 "ld 3,96(11)\n\t" \
3223 "std 3,136(1)\n\t" \
3224 /* arg11 */ \
3225 "ld 3,88(11)\n\t" \
3226 "std 3,128(1)\n\t" \
3227 /* arg10 */ \
3228 "ld 3,80(11)\n\t" \
3229 "std 3,120(1)\n\t" \
3230 /* arg9 */ \
3231 "ld 3,72(11)\n\t" \
3232 "std 3,112(1)\n\t" \
3233 /* args1-8 */ \
3234 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3235 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3236 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3237 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3238 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3239 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3240 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3241 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3242 "ld 11, 0(11)\n\t" /* target->r11 */ \
3243 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3244 "mr 11,%1\n\t" \
3245 "mr %0,3\n\t" \
3246 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00003247 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00003248 : /*out*/ "=r" (_res) \
3249 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00003250 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00003251 ); \
3252 lval = (__typeof__(lval)) _res; \
3253 } while (0)
3254
carllcae0cc22014-08-07 23:17:29 +00003255#endif /* PLAT_ppc64be_linux */
sewardjf5c1a7f2006-10-17 01:32:48 +00003256
carll582d5822014-08-07 23:35:54 +00003257/* ------------------------- ppc64le-linux ----------------------- */
3258#if defined(PLAT_ppc64le_linux)
3259
3260/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3261
3262/* These regs are trashed by the hidden call. */
3263#define __CALLER_SAVED_REGS \
3264 "lr", "ctr", "xer", \
3265 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3266 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3267 "r11", "r12", "r13"
3268
3269/* Macros to save and align the stack before making a function
3270 call and restore it afterwards as gcc may not keep the stack
3271 pointer aligned if it doesn't realise calls are being made
3272 to other functions. */
3273
3274#define VALGRIND_ALIGN_STACK \
3275 "mr 28,1\n\t" \
3276 "rldicr 1,1,0,59\n\t"
3277#define VALGRIND_RESTORE_STACK \
3278 "mr 1,28\n\t"
3279
3280/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
3281 long) == 8. */
3282
3283#define CALL_FN_W_v(lval, orig) \
3284 do { \
3285 volatile OrigFn _orig = (orig); \
3286 volatile unsigned long _argvec[3+0]; \
3287 volatile unsigned long _res; \
3288 /* _argvec[0] holds current r2 across the call */ \
3289 _argvec[1] = (unsigned long)_orig.r2; \
3290 _argvec[2] = (unsigned long)_orig.nraddr; \
3291 __asm__ volatile( \
3292 VALGRIND_ALIGN_STACK \
3293 "mr 12,%1\n\t" \
3294 "std 2,-16(12)\n\t" /* save tocptr */ \
3295 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3296 "ld 12, 0(12)\n\t" /* target->r12 */ \
3297 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3298 "mr 12,%1\n\t" \
3299 "mr %0,3\n\t" \
3300 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3301 VALGRIND_RESTORE_STACK \
3302 : /*out*/ "=r" (_res) \
3303 : /*in*/ "r" (&_argvec[2]) \
3304 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3305 ); \
3306 lval = (__typeof__(lval)) _res; \
3307 } while (0)
3308
3309#define CALL_FN_W_W(lval, orig, arg1) \
3310 do { \
3311 volatile OrigFn _orig = (orig); \
3312 volatile unsigned long _argvec[3+1]; \
3313 volatile unsigned long _res; \
3314 /* _argvec[0] holds current r2 across the call */ \
3315 _argvec[1] = (unsigned long)_orig.r2; \
3316 _argvec[2] = (unsigned long)_orig.nraddr; \
3317 _argvec[2+1] = (unsigned long)arg1; \
3318 __asm__ volatile( \
3319 VALGRIND_ALIGN_STACK \
3320 "mr 12,%1\n\t" \
3321 "std 2,-16(12)\n\t" /* save tocptr */ \
3322 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3323 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3324 "ld 12, 0(12)\n\t" /* target->r12 */ \
3325 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3326 "mr 12,%1\n\t" \
3327 "mr %0,3\n\t" \
3328 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3329 VALGRIND_RESTORE_STACK \
3330 : /*out*/ "=r" (_res) \
3331 : /*in*/ "r" (&_argvec[2]) \
3332 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3333 ); \
3334 lval = (__typeof__(lval)) _res; \
3335 } while (0)
3336
3337#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3338 do { \
3339 volatile OrigFn _orig = (orig); \
3340 volatile unsigned long _argvec[3+2]; \
3341 volatile unsigned long _res; \
3342 /* _argvec[0] holds current r2 across the call */ \
3343 _argvec[1] = (unsigned long)_orig.r2; \
3344 _argvec[2] = (unsigned long)_orig.nraddr; \
3345 _argvec[2+1] = (unsigned long)arg1; \
3346 _argvec[2+2] = (unsigned long)arg2; \
3347 __asm__ volatile( \
3348 VALGRIND_ALIGN_STACK \
3349 "mr 12,%1\n\t" \
3350 "std 2,-16(12)\n\t" /* save tocptr */ \
3351 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3352 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3353 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3354 "ld 12, 0(12)\n\t" /* target->r12 */ \
3355 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3356 "mr 12,%1\n\t" \
3357 "mr %0,3\n\t" \
3358 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3359 VALGRIND_RESTORE_STACK \
3360 : /*out*/ "=r" (_res) \
3361 : /*in*/ "r" (&_argvec[2]) \
3362 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3363 ); \
3364 lval = (__typeof__(lval)) _res; \
3365 } while (0)
3366
3367#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3368 do { \
3369 volatile OrigFn _orig = (orig); \
3370 volatile unsigned long _argvec[3+3]; \
3371 volatile unsigned long _res; \
3372 /* _argvec[0] holds current r2 across the call */ \
3373 _argvec[1] = (unsigned long)_orig.r2; \
3374 _argvec[2] = (unsigned long)_orig.nraddr; \
3375 _argvec[2+1] = (unsigned long)arg1; \
3376 _argvec[2+2] = (unsigned long)arg2; \
3377 _argvec[2+3] = (unsigned long)arg3; \
3378 __asm__ volatile( \
3379 VALGRIND_ALIGN_STACK \
3380 "mr 12,%1\n\t" \
3381 "std 2,-16(12)\n\t" /* save tocptr */ \
3382 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3383 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3384 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3385 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3386 "ld 12, 0(12)\n\t" /* target->r12 */ \
3387 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3388 "mr 12,%1\n\t" \
3389 "mr %0,3\n\t" \
3390 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3391 VALGRIND_RESTORE_STACK \
3392 : /*out*/ "=r" (_res) \
3393 : /*in*/ "r" (&_argvec[2]) \
3394 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3395 ); \
3396 lval = (__typeof__(lval)) _res; \
3397 } while (0)
3398
3399#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3400 do { \
3401 volatile OrigFn _orig = (orig); \
3402 volatile unsigned long _argvec[3+4]; \
3403 volatile unsigned long _res; \
3404 /* _argvec[0] holds current r2 across the call */ \
3405 _argvec[1] = (unsigned long)_orig.r2; \
3406 _argvec[2] = (unsigned long)_orig.nraddr; \
3407 _argvec[2+1] = (unsigned long)arg1; \
3408 _argvec[2+2] = (unsigned long)arg2; \
3409 _argvec[2+3] = (unsigned long)arg3; \
3410 _argvec[2+4] = (unsigned long)arg4; \
3411 __asm__ volatile( \
3412 VALGRIND_ALIGN_STACK \
3413 "mr 12,%1\n\t" \
3414 "std 2,-16(12)\n\t" /* save tocptr */ \
3415 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3416 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3417 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3418 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3419 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3420 "ld 12, 0(12)\n\t" /* target->r12 */ \
3421 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3422 "mr 12,%1\n\t" \
3423 "mr %0,3\n\t" \
3424 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3425 VALGRIND_RESTORE_STACK \
3426 : /*out*/ "=r" (_res) \
3427 : /*in*/ "r" (&_argvec[2]) \
3428 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3429 ); \
3430 lval = (__typeof__(lval)) _res; \
3431 } while (0)
3432
3433#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3434 do { \
3435 volatile OrigFn _orig = (orig); \
3436 volatile unsigned long _argvec[3+5]; \
3437 volatile unsigned long _res; \
3438 /* _argvec[0] holds current r2 across the call */ \
3439 _argvec[1] = (unsigned long)_orig.r2; \
3440 _argvec[2] = (unsigned long)_orig.nraddr; \
3441 _argvec[2+1] = (unsigned long)arg1; \
3442 _argvec[2+2] = (unsigned long)arg2; \
3443 _argvec[2+3] = (unsigned long)arg3; \
3444 _argvec[2+4] = (unsigned long)arg4; \
3445 _argvec[2+5] = (unsigned long)arg5; \
3446 __asm__ volatile( \
3447 VALGRIND_ALIGN_STACK \
3448 "mr 12,%1\n\t" \
3449 "std 2,-16(12)\n\t" /* save tocptr */ \
3450 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3451 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3452 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3453 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3454 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3455 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3456 "ld 12, 0(12)\n\t" /* target->r12 */ \
3457 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3458 "mr 12,%1\n\t" \
3459 "mr %0,3\n\t" \
3460 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3461 VALGRIND_RESTORE_STACK \
3462 : /*out*/ "=r" (_res) \
3463 : /*in*/ "r" (&_argvec[2]) \
3464 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3465 ); \
3466 lval = (__typeof__(lval)) _res; \
3467 } while (0)
3468
3469#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3470 do { \
3471 volatile OrigFn _orig = (orig); \
3472 volatile unsigned long _argvec[3+6]; \
3473 volatile unsigned long _res; \
3474 /* _argvec[0] holds current r2 across the call */ \
3475 _argvec[1] = (unsigned long)_orig.r2; \
3476 _argvec[2] = (unsigned long)_orig.nraddr; \
3477 _argvec[2+1] = (unsigned long)arg1; \
3478 _argvec[2+2] = (unsigned long)arg2; \
3479 _argvec[2+3] = (unsigned long)arg3; \
3480 _argvec[2+4] = (unsigned long)arg4; \
3481 _argvec[2+5] = (unsigned long)arg5; \
3482 _argvec[2+6] = (unsigned long)arg6; \
3483 __asm__ volatile( \
3484 VALGRIND_ALIGN_STACK \
3485 "mr 12,%1\n\t" \
3486 "std 2,-16(12)\n\t" /* save tocptr */ \
3487 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3488 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3489 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3490 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3491 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3492 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3493 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3494 "ld 12, 0(12)\n\t" /* target->r12 */ \
3495 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3496 "mr 12,%1\n\t" \
3497 "mr %0,3\n\t" \
3498 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3499 VALGRIND_RESTORE_STACK \
3500 : /*out*/ "=r" (_res) \
3501 : /*in*/ "r" (&_argvec[2]) \
3502 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3503 ); \
3504 lval = (__typeof__(lval)) _res; \
3505 } while (0)
3506
3507#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3508 arg7) \
3509 do { \
3510 volatile OrigFn _orig = (orig); \
3511 volatile unsigned long _argvec[3+7]; \
3512 volatile unsigned long _res; \
3513 /* _argvec[0] holds current r2 across the call */ \
3514 _argvec[1] = (unsigned long)_orig.r2; \
3515 _argvec[2] = (unsigned long)_orig.nraddr; \
3516 _argvec[2+1] = (unsigned long)arg1; \
3517 _argvec[2+2] = (unsigned long)arg2; \
3518 _argvec[2+3] = (unsigned long)arg3; \
3519 _argvec[2+4] = (unsigned long)arg4; \
3520 _argvec[2+5] = (unsigned long)arg5; \
3521 _argvec[2+6] = (unsigned long)arg6; \
3522 _argvec[2+7] = (unsigned long)arg7; \
3523 __asm__ volatile( \
3524 VALGRIND_ALIGN_STACK \
3525 "mr 12,%1\n\t" \
3526 "std 2,-16(12)\n\t" /* save tocptr */ \
3527 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3528 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3529 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3530 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3531 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3532 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3533 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3534 "ld 9, 56(12)\n\t" /* arg7->r9 */ \
3535 "ld 12, 0(12)\n\t" /* target->r12 */ \
3536 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3537 "mr 12,%1\n\t" \
3538 "mr %0,3\n\t" \
3539 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3540 VALGRIND_RESTORE_STACK \
3541 : /*out*/ "=r" (_res) \
3542 : /*in*/ "r" (&_argvec[2]) \
3543 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3544 ); \
3545 lval = (__typeof__(lval)) _res; \
3546 } while (0)
3547
3548#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3549 arg7,arg8) \
3550 do { \
3551 volatile OrigFn _orig = (orig); \
3552 volatile unsigned long _argvec[3+8]; \
3553 volatile unsigned long _res; \
3554 /* _argvec[0] holds current r2 across the call */ \
3555 _argvec[1] = (unsigned long)_orig.r2; \
3556 _argvec[2] = (unsigned long)_orig.nraddr; \
3557 _argvec[2+1] = (unsigned long)arg1; \
3558 _argvec[2+2] = (unsigned long)arg2; \
3559 _argvec[2+3] = (unsigned long)arg3; \
3560 _argvec[2+4] = (unsigned long)arg4; \
3561 _argvec[2+5] = (unsigned long)arg5; \
3562 _argvec[2+6] = (unsigned long)arg6; \
3563 _argvec[2+7] = (unsigned long)arg7; \
3564 _argvec[2+8] = (unsigned long)arg8; \
3565 __asm__ volatile( \
3566 VALGRIND_ALIGN_STACK \
3567 "mr 12,%1\n\t" \
3568 "std 2,-16(12)\n\t" /* save tocptr */ \
3569 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3570 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3571 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3572 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3573 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3574 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3575 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3576 "ld 9, 56(12)\n\t" /* arg7->r9 */ \
3577 "ld 10, 64(12)\n\t" /* arg8->r10 */ \
3578 "ld 12, 0(12)\n\t" /* target->r12 */ \
3579 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3580 "mr 12,%1\n\t" \
3581 "mr %0,3\n\t" \
3582 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3583 VALGRIND_RESTORE_STACK \
3584 : /*out*/ "=r" (_res) \
3585 : /*in*/ "r" (&_argvec[2]) \
3586 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3587 ); \
3588 lval = (__typeof__(lval)) _res; \
3589 } while (0)
3590
3591#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3592 arg7,arg8,arg9) \
3593 do { \
3594 volatile OrigFn _orig = (orig); \
3595 volatile unsigned long _argvec[3+9]; \
3596 volatile unsigned long _res; \
3597 /* _argvec[0] holds current r2 across the call */ \
3598 _argvec[1] = (unsigned long)_orig.r2; \
3599 _argvec[2] = (unsigned long)_orig.nraddr; \
3600 _argvec[2+1] = (unsigned long)arg1; \
3601 _argvec[2+2] = (unsigned long)arg2; \
3602 _argvec[2+3] = (unsigned long)arg3; \
3603 _argvec[2+4] = (unsigned long)arg4; \
3604 _argvec[2+5] = (unsigned long)arg5; \
3605 _argvec[2+6] = (unsigned long)arg6; \
3606 _argvec[2+7] = (unsigned long)arg7; \
3607 _argvec[2+8] = (unsigned long)arg8; \
3608 _argvec[2+9] = (unsigned long)arg9; \
3609 __asm__ volatile( \
3610 VALGRIND_ALIGN_STACK \
3611 "mr 12,%1\n\t" \
3612 "std 2,-16(12)\n\t" /* save tocptr */ \
3613 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3614 "addi 1,1,-128\n\t" /* expand stack frame */ \
3615 /* arg9 */ \
3616 "ld 3,72(12)\n\t" \
3617 "std 3,96(1)\n\t" \
3618 /* args1-8 */ \
3619 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3620 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3621 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3622 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3623 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3624 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3625 "ld 9, 56(12)\n\t" /* arg7->r9 */ \
3626 "ld 10, 64(12)\n\t" /* arg8->r10 */ \
3627 "ld 12, 0(12)\n\t" /* target->r12 */ \
3628 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3629 "mr 12,%1\n\t" \
3630 "mr %0,3\n\t" \
3631 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3632 VALGRIND_RESTORE_STACK \
3633 : /*out*/ "=r" (_res) \
3634 : /*in*/ "r" (&_argvec[2]) \
3635 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3636 ); \
3637 lval = (__typeof__(lval)) _res; \
3638 } while (0)
3639
3640#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3641 arg7,arg8,arg9,arg10) \
3642 do { \
3643 volatile OrigFn _orig = (orig); \
3644 volatile unsigned long _argvec[3+10]; \
3645 volatile unsigned long _res; \
3646 /* _argvec[0] holds current r2 across the call */ \
3647 _argvec[1] = (unsigned long)_orig.r2; \
3648 _argvec[2] = (unsigned long)_orig.nraddr; \
3649 _argvec[2+1] = (unsigned long)arg1; \
3650 _argvec[2+2] = (unsigned long)arg2; \
3651 _argvec[2+3] = (unsigned long)arg3; \
3652 _argvec[2+4] = (unsigned long)arg4; \
3653 _argvec[2+5] = (unsigned long)arg5; \
3654 _argvec[2+6] = (unsigned long)arg6; \
3655 _argvec[2+7] = (unsigned long)arg7; \
3656 _argvec[2+8] = (unsigned long)arg8; \
3657 _argvec[2+9] = (unsigned long)arg9; \
3658 _argvec[2+10] = (unsigned long)arg10; \
3659 __asm__ volatile( \
3660 VALGRIND_ALIGN_STACK \
3661 "mr 12,%1\n\t" \
3662 "std 2,-16(12)\n\t" /* save tocptr */ \
3663 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3664 "addi 1,1,-128\n\t" /* expand stack frame */ \
3665 /* arg10 */ \
3666 "ld 3,80(12)\n\t" \
3667 "std 3,104(1)\n\t" \
3668 /* arg9 */ \
3669 "ld 3,72(12)\n\t" \
3670 "std 3,96(1)\n\t" \
3671 /* args1-8 */ \
3672 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3673 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3674 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3675 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3676 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3677 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3678 "ld 9, 56(12)\n\t" /* arg7->r9 */ \
3679 "ld 10, 64(12)\n\t" /* arg8->r10 */ \
3680 "ld 12, 0(12)\n\t" /* target->r12 */ \
3681 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3682 "mr 12,%1\n\t" \
3683 "mr %0,3\n\t" \
3684 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3685 VALGRIND_RESTORE_STACK \
3686 : /*out*/ "=r" (_res) \
3687 : /*in*/ "r" (&_argvec[2]) \
3688 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3689 ); \
3690 lval = (__typeof__(lval)) _res; \
3691 } while (0)
3692
3693#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3694 arg7,arg8,arg9,arg10,arg11) \
3695 do { \
3696 volatile OrigFn _orig = (orig); \
3697 volatile unsigned long _argvec[3+11]; \
3698 volatile unsigned long _res; \
3699 /* _argvec[0] holds current r2 across the call */ \
3700 _argvec[1] = (unsigned long)_orig.r2; \
3701 _argvec[2] = (unsigned long)_orig.nraddr; \
3702 _argvec[2+1] = (unsigned long)arg1; \
3703 _argvec[2+2] = (unsigned long)arg2; \
3704 _argvec[2+3] = (unsigned long)arg3; \
3705 _argvec[2+4] = (unsigned long)arg4; \
3706 _argvec[2+5] = (unsigned long)arg5; \
3707 _argvec[2+6] = (unsigned long)arg6; \
3708 _argvec[2+7] = (unsigned long)arg7; \
3709 _argvec[2+8] = (unsigned long)arg8; \
3710 _argvec[2+9] = (unsigned long)arg9; \
3711 _argvec[2+10] = (unsigned long)arg10; \
3712 _argvec[2+11] = (unsigned long)arg11; \
3713 __asm__ volatile( \
3714 VALGRIND_ALIGN_STACK \
3715 "mr 12,%1\n\t" \
3716 "std 2,-16(12)\n\t" /* save tocptr */ \
3717 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3718 "addi 1,1,-144\n\t" /* expand stack frame */ \
3719 /* arg11 */ \
3720 "ld 3,88(12)\n\t" \
3721 "std 3,112(1)\n\t" \
3722 /* arg10 */ \
3723 "ld 3,80(12)\n\t" \
3724 "std 3,104(1)\n\t" \
3725 /* arg9 */ \
3726 "ld 3,72(12)\n\t" \
3727 "std 3,96(1)\n\t" \
3728 /* args1-8 */ \
3729 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3730 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3731 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3732 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3733 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3734 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3735 "ld 9, 56(12)\n\t" /* arg7->r9 */ \
3736 "ld 10, 64(12)\n\t" /* arg8->r10 */ \
3737 "ld 12, 0(12)\n\t" /* target->r12 */ \
3738 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3739 "mr 12,%1\n\t" \
3740 "mr %0,3\n\t" \
3741 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3742 VALGRIND_RESTORE_STACK \
3743 : /*out*/ "=r" (_res) \
3744 : /*in*/ "r" (&_argvec[2]) \
3745 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3746 ); \
3747 lval = (__typeof__(lval)) _res; \
3748 } while (0)
3749
3750#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3751 arg7,arg8,arg9,arg10,arg11,arg12) \
3752 do { \
3753 volatile OrigFn _orig = (orig); \
3754 volatile unsigned long _argvec[3+12]; \
3755 volatile unsigned long _res; \
3756 /* _argvec[0] holds current r2 across the call */ \
3757 _argvec[1] = (unsigned long)_orig.r2; \
3758 _argvec[2] = (unsigned long)_orig.nraddr; \
3759 _argvec[2+1] = (unsigned long)arg1; \
3760 _argvec[2+2] = (unsigned long)arg2; \
3761 _argvec[2+3] = (unsigned long)arg3; \
3762 _argvec[2+4] = (unsigned long)arg4; \
3763 _argvec[2+5] = (unsigned long)arg5; \
3764 _argvec[2+6] = (unsigned long)arg6; \
3765 _argvec[2+7] = (unsigned long)arg7; \
3766 _argvec[2+8] = (unsigned long)arg8; \
3767 _argvec[2+9] = (unsigned long)arg9; \
3768 _argvec[2+10] = (unsigned long)arg10; \
3769 _argvec[2+11] = (unsigned long)arg11; \
3770 _argvec[2+12] = (unsigned long)arg12; \
3771 __asm__ volatile( \
3772 VALGRIND_ALIGN_STACK \
3773 "mr 12,%1\n\t" \
3774 "std 2,-16(12)\n\t" /* save tocptr */ \
3775 "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
3776 "addi 1,1,-144\n\t" /* expand stack frame */ \
3777 /* arg12 */ \
3778 "ld 3,96(12)\n\t" \
3779 "std 3,120(1)\n\t" \
3780 /* arg11 */ \
3781 "ld 3,88(12)\n\t" \
3782 "std 3,112(1)\n\t" \
3783 /* arg10 */ \
3784 "ld 3,80(12)\n\t" \
3785 "std 3,104(1)\n\t" \
3786 /* arg9 */ \
3787 "ld 3,72(12)\n\t" \
3788 "std 3,96(1)\n\t" \
3789 /* args1-8 */ \
3790 "ld 3, 8(12)\n\t" /* arg1->r3 */ \
3791 "ld 4, 16(12)\n\t" /* arg2->r4 */ \
3792 "ld 5, 24(12)\n\t" /* arg3->r5 */ \
3793 "ld 6, 32(12)\n\t" /* arg4->r6 */ \
3794 "ld 7, 40(12)\n\t" /* arg5->r7 */ \
3795 "ld 8, 48(12)\n\t" /* arg6->r8 */ \
3796 "ld 9, 56(12)\n\t" /* arg7->r9 */ \
3797 "ld 10, 64(12)\n\t" /* arg8->r10 */ \
3798 "ld 12, 0(12)\n\t" /* target->r12 */ \
3799 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
3800 "mr 12,%1\n\t" \
3801 "mr %0,3\n\t" \
3802 "ld 2,-16(12)\n\t" /* restore tocptr */ \
3803 VALGRIND_RESTORE_STACK \
3804 : /*out*/ "=r" (_res) \
3805 : /*in*/ "r" (&_argvec[2]) \
3806 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
3807 ); \
3808 lval = (__typeof__(lval)) _res; \
3809 } while (0)
3810
3811#endif /* PLAT_ppc64le_linux */
3812
sewardj59570ff2010-01-01 11:59:33 +00003813/* ------------------------- arm-linux ------------------------- */
3814
3815#if defined(PLAT_arm_linux)
3816
3817/* These regs are trashed by the hidden call. */
sewardj87d812e2015-02-11 19:46:27 +00003818#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4", "r12", "r14"
sewardj59570ff2010-01-01 11:59:33 +00003819
tom4118e0f2012-08-02 09:23:45 +00003820/* Macros to save and align the stack before making a function
3821 call and restore it afterwards as gcc may not keep the stack
3822 pointer aligned if it doesn't realise calls are being made
3823 to other functions. */
3824
sewardj567e5bb2012-08-04 19:23:54 +00003825/* This is a bit tricky. We store the original stack pointer in r10
3826 as it is callee-saves. gcc doesn't allow the use of r11 for some
3827 reason. Also, we can't directly "bic" the stack pointer in thumb
3828 mode since r13 isn't an allowed register number in that context.
3829 So use r4 as a temporary, since that is about to get trashed
3830 anyway, just after each use of this macro. Side effect is we need
3831 to be very careful about any future changes, since
3832 VALGRIND_ALIGN_STACK simply assumes r4 is usable. */
tom4118e0f2012-08-02 09:23:45 +00003833#define VALGRIND_ALIGN_STACK \
sewardj567e5bb2012-08-04 19:23:54 +00003834 "mov r10, sp\n\t" \
3835 "mov r4, sp\n\t" \
3836 "bic r4, r4, #7\n\t" \
3837 "mov sp, r4\n\t"
tom4118e0f2012-08-02 09:23:45 +00003838#define VALGRIND_RESTORE_STACK \
sewardj567e5bb2012-08-04 19:23:54 +00003839 "mov sp, r10\n\t"
tom4118e0f2012-08-02 09:23:45 +00003840
sewardj59570ff2010-01-01 11:59:33 +00003841/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
3842 long) == 4. */
3843
3844#define CALL_FN_W_v(lval, orig) \
3845 do { \
3846 volatile OrigFn _orig = (orig); \
3847 volatile unsigned long _argvec[1]; \
3848 volatile unsigned long _res; \
3849 _argvec[0] = (unsigned long)_orig.nraddr; \
3850 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003851 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003852 "ldr r4, [%1] \n\t" /* target->r4 */ \
3853 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003854 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003855 "mov %0, r0\n" \
3856 : /*out*/ "=r" (_res) \
3857 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003858 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003859 ); \
3860 lval = (__typeof__(lval)) _res; \
3861 } while (0)
3862
3863#define CALL_FN_W_W(lval, orig, arg1) \
3864 do { \
3865 volatile OrigFn _orig = (orig); \
3866 volatile unsigned long _argvec[2]; \
3867 volatile unsigned long _res; \
3868 _argvec[0] = (unsigned long)_orig.nraddr; \
3869 _argvec[1] = (unsigned long)(arg1); \
3870 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003871 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003872 "ldr r0, [%1, #4] \n\t" \
3873 "ldr r4, [%1] \n\t" /* target->r4 */ \
3874 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003875 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003876 "mov %0, r0\n" \
3877 : /*out*/ "=r" (_res) \
3878 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003879 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003880 ); \
3881 lval = (__typeof__(lval)) _res; \
3882 } while (0)
3883
3884#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3885 do { \
3886 volatile OrigFn _orig = (orig); \
3887 volatile unsigned long _argvec[3]; \
3888 volatile unsigned long _res; \
3889 _argvec[0] = (unsigned long)_orig.nraddr; \
3890 _argvec[1] = (unsigned long)(arg1); \
3891 _argvec[2] = (unsigned long)(arg2); \
3892 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003893 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003894 "ldr r0, [%1, #4] \n\t" \
3895 "ldr r1, [%1, #8] \n\t" \
3896 "ldr r4, [%1] \n\t" /* target->r4 */ \
3897 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003898 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003899 "mov %0, r0\n" \
3900 : /*out*/ "=r" (_res) \
3901 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003902 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003903 ); \
3904 lval = (__typeof__(lval)) _res; \
3905 } while (0)
3906
3907#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3908 do { \
3909 volatile OrigFn _orig = (orig); \
3910 volatile unsigned long _argvec[4]; \
3911 volatile unsigned long _res; \
3912 _argvec[0] = (unsigned long)_orig.nraddr; \
3913 _argvec[1] = (unsigned long)(arg1); \
3914 _argvec[2] = (unsigned long)(arg2); \
3915 _argvec[3] = (unsigned long)(arg3); \
3916 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003917 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003918 "ldr r0, [%1, #4] \n\t" \
3919 "ldr r1, [%1, #8] \n\t" \
3920 "ldr r2, [%1, #12] \n\t" \
3921 "ldr r4, [%1] \n\t" /* target->r4 */ \
3922 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003923 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003924 "mov %0, r0\n" \
3925 : /*out*/ "=r" (_res) \
3926 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003927 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003928 ); \
3929 lval = (__typeof__(lval)) _res; \
3930 } while (0)
3931
3932#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3933 do { \
3934 volatile OrigFn _orig = (orig); \
3935 volatile unsigned long _argvec[5]; \
3936 volatile unsigned long _res; \
3937 _argvec[0] = (unsigned long)_orig.nraddr; \
3938 _argvec[1] = (unsigned long)(arg1); \
3939 _argvec[2] = (unsigned long)(arg2); \
3940 _argvec[3] = (unsigned long)(arg3); \
3941 _argvec[4] = (unsigned long)(arg4); \
3942 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003943 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003944 "ldr r0, [%1, #4] \n\t" \
3945 "ldr r1, [%1, #8] \n\t" \
3946 "ldr r2, [%1, #12] \n\t" \
3947 "ldr r3, [%1, #16] \n\t" \
3948 "ldr r4, [%1] \n\t" /* target->r4 */ \
3949 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003950 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003951 "mov %0, r0" \
3952 : /*out*/ "=r" (_res) \
3953 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003954 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003955 ); \
3956 lval = (__typeof__(lval)) _res; \
3957 } while (0)
3958
3959#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3960 do { \
3961 volatile OrigFn _orig = (orig); \
3962 volatile unsigned long _argvec[6]; \
3963 volatile unsigned long _res; \
3964 _argvec[0] = (unsigned long)_orig.nraddr; \
3965 _argvec[1] = (unsigned long)(arg1); \
3966 _argvec[2] = (unsigned long)(arg2); \
3967 _argvec[3] = (unsigned long)(arg3); \
3968 _argvec[4] = (unsigned long)(arg4); \
3969 _argvec[5] = (unsigned long)(arg5); \
3970 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003971 VALGRIND_ALIGN_STACK \
3972 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003973 "ldr r0, [%1, #20] \n\t" \
3974 "push {r0} \n\t" \
3975 "ldr r0, [%1, #4] \n\t" \
3976 "ldr r1, [%1, #8] \n\t" \
3977 "ldr r2, [%1, #12] \n\t" \
3978 "ldr r3, [%1, #16] \n\t" \
3979 "ldr r4, [%1] \n\t" /* target->r4 */ \
3980 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003981 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003982 "mov %0, r0" \
3983 : /*out*/ "=r" (_res) \
3984 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003985 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003986 ); \
3987 lval = (__typeof__(lval)) _res; \
3988 } while (0)
3989
3990#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3991 do { \
3992 volatile OrigFn _orig = (orig); \
3993 volatile unsigned long _argvec[7]; \
3994 volatile unsigned long _res; \
3995 _argvec[0] = (unsigned long)_orig.nraddr; \
3996 _argvec[1] = (unsigned long)(arg1); \
3997 _argvec[2] = (unsigned long)(arg2); \
3998 _argvec[3] = (unsigned long)(arg3); \
3999 _argvec[4] = (unsigned long)(arg4); \
4000 _argvec[5] = (unsigned long)(arg5); \
4001 _argvec[6] = (unsigned long)(arg6); \
4002 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00004003 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00004004 "ldr r0, [%1, #20] \n\t" \
4005 "ldr r1, [%1, #24] \n\t" \
4006 "push {r0, r1} \n\t" \
4007 "ldr r0, [%1, #4] \n\t" \
4008 "ldr r1, [%1, #8] \n\t" \
4009 "ldr r2, [%1, #12] \n\t" \
4010 "ldr r3, [%1, #16] \n\t" \
4011 "ldr r4, [%1] \n\t" /* target->r4 */ \
4012 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00004013 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00004014 "mov %0, r0" \
4015 : /*out*/ "=r" (_res) \
4016 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00004017 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00004018 ); \
4019 lval = (__typeof__(lval)) _res; \
4020 } while (0)
4021
4022#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4023 arg7) \
4024 do { \
4025 volatile OrigFn _orig = (orig); \
4026 volatile unsigned long _argvec[8]; \
4027 volatile unsigned long _res; \
4028 _argvec[0] = (unsigned long)_orig.nraddr; \
4029 _argvec[1] = (unsigned long)(arg1); \
4030 _argvec[2] = (unsigned long)(arg2); \
4031 _argvec[3] = (unsigned long)(arg3); \
4032 _argvec[4] = (unsigned long)(arg4); \
4033 _argvec[5] = (unsigned long)(arg5); \
4034 _argvec[6] = (unsigned long)(arg6); \
4035 _argvec[7] = (unsigned long)(arg7); \
4036 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00004037 VALGRIND_ALIGN_STACK \
4038 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00004039 "ldr r0, [%1, #20] \n\t" \
4040 "ldr r1, [%1, #24] \n\t" \
4041 "ldr r2, [%1, #28] \n\t" \
4042 "push {r0, r1, r2} \n\t" \
4043 "ldr r0, [%1, #4] \n\t" \
4044 "ldr r1, [%1, #8] \n\t" \
4045 "ldr r2, [%1, #12] \n\t" \
4046 "ldr r3, [%1, #16] \n\t" \
4047 "ldr r4, [%1] \n\t" /* target->r4 */ \
4048 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00004049 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00004050 "mov %0, r0" \
4051 : /*out*/ "=r" (_res) \
4052 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00004053 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00004054 ); \
4055 lval = (__typeof__(lval)) _res; \
4056 } while (0)
4057
4058#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4059 arg7,arg8) \
4060 do { \
4061 volatile OrigFn _orig = (orig); \
4062 volatile unsigned long _argvec[9]; \
4063 volatile unsigned long _res; \
4064 _argvec[0] = (unsigned long)_orig.nraddr; \
4065 _argvec[1] = (unsigned long)(arg1); \
4066 _argvec[2] = (unsigned long)(arg2); \
4067 _argvec[3] = (unsigned long)(arg3); \
4068 _argvec[4] = (unsigned long)(arg4); \
4069 _argvec[5] = (unsigned long)(arg5); \
4070 _argvec[6] = (unsigned long)(arg6); \
4071 _argvec[7] = (unsigned long)(arg7); \
4072 _argvec[8] = (unsigned long)(arg8); \
4073 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00004074 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00004075 "ldr r0, [%1, #20] \n\t" \
4076 "ldr r1, [%1, #24] \n\t" \
4077 "ldr r2, [%1, #28] \n\t" \
4078 "ldr r3, [%1, #32] \n\t" \
4079 "push {r0, r1, r2, r3} \n\t" \
4080 "ldr r0, [%1, #4] \n\t" \
4081 "ldr r1, [%1, #8] \n\t" \
4082 "ldr r2, [%1, #12] \n\t" \
4083 "ldr r3, [%1, #16] \n\t" \
4084 "ldr r4, [%1] \n\t" /* target->r4 */ \
4085 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00004086 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00004087 "mov %0, r0" \
4088 : /*out*/ "=r" (_res) \
4089 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00004090 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00004091 ); \
4092 lval = (__typeof__(lval)) _res; \
4093 } while (0)
4094
4095#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4096 arg7,arg8,arg9) \
4097 do { \
4098 volatile OrigFn _orig = (orig); \
4099 volatile unsigned long _argvec[10]; \
4100 volatile unsigned long _res; \
4101 _argvec[0] = (unsigned long)_orig.nraddr; \
4102 _argvec[1] = (unsigned long)(arg1); \
4103 _argvec[2] = (unsigned long)(arg2); \
4104 _argvec[3] = (unsigned long)(arg3); \
4105 _argvec[4] = (unsigned long)(arg4); \
4106 _argvec[5] = (unsigned long)(arg5); \
4107 _argvec[6] = (unsigned long)(arg6); \
4108 _argvec[7] = (unsigned long)(arg7); \
4109 _argvec[8] = (unsigned long)(arg8); \
4110 _argvec[9] = (unsigned long)(arg9); \
4111 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00004112 VALGRIND_ALIGN_STACK \
4113 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00004114 "ldr r0, [%1, #20] \n\t" \
4115 "ldr r1, [%1, #24] \n\t" \
4116 "ldr r2, [%1, #28] \n\t" \
4117 "ldr r3, [%1, #32] \n\t" \
4118 "ldr r4, [%1, #36] \n\t" \
4119 "push {r0, r1, r2, r3, r4} \n\t" \
4120 "ldr r0, [%1, #4] \n\t" \
4121 "ldr r1, [%1, #8] \n\t" \
4122 "ldr r2, [%1, #12] \n\t" \
4123 "ldr r3, [%1, #16] \n\t" \
4124 "ldr r4, [%1] \n\t" /* target->r4 */ \
4125 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00004126 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00004127 "mov %0, r0" \
4128 : /*out*/ "=r" (_res) \
4129 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00004130 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00004131 ); \
4132 lval = (__typeof__(lval)) _res; \
4133 } while (0)
4134
4135#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4136 arg7,arg8,arg9,arg10) \
4137 do { \
4138 volatile OrigFn _orig = (orig); \
4139 volatile unsigned long _argvec[11]; \
4140 volatile unsigned long _res; \
4141 _argvec[0] = (unsigned long)_orig.nraddr; \
4142 _argvec[1] = (unsigned long)(arg1); \
4143 _argvec[2] = (unsigned long)(arg2); \
4144 _argvec[3] = (unsigned long)(arg3); \
4145 _argvec[4] = (unsigned long)(arg4); \
4146 _argvec[5] = (unsigned long)(arg5); \
4147 _argvec[6] = (unsigned long)(arg6); \
4148 _argvec[7] = (unsigned long)(arg7); \
4149 _argvec[8] = (unsigned long)(arg8); \
4150 _argvec[9] = (unsigned long)(arg9); \
4151 _argvec[10] = (unsigned long)(arg10); \
4152 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00004153 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00004154 "ldr r0, [%1, #40] \n\t" \
4155 "push {r0} \n\t" \
4156 "ldr r0, [%1, #20] \n\t" \
4157 "ldr r1, [%1, #24] \n\t" \
4158 "ldr r2, [%1, #28] \n\t" \
4159 "ldr r3, [%1, #32] \n\t" \
4160 "ldr r4, [%1, #36] \n\t" \
4161 "push {r0, r1, r2, r3, r4} \n\t" \
4162 "ldr r0, [%1, #4] \n\t" \
4163 "ldr r1, [%1, #8] \n\t" \
4164 "ldr r2, [%1, #12] \n\t" \
4165 "ldr r3, [%1, #16] \n\t" \
4166 "ldr r4, [%1] \n\t" /* target->r4 */ \
4167 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00004168 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00004169 "mov %0, r0" \
4170 : /*out*/ "=r" (_res) \
4171 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00004172 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00004173 ); \
4174 lval = (__typeof__(lval)) _res; \
4175 } while (0)
4176
4177#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
4178 arg6,arg7,arg8,arg9,arg10, \
4179 arg11) \
4180 do { \
4181 volatile OrigFn _orig = (orig); \
4182 volatile unsigned long _argvec[12]; \
4183 volatile unsigned long _res; \
4184 _argvec[0] = (unsigned long)_orig.nraddr; \
4185 _argvec[1] = (unsigned long)(arg1); \
4186 _argvec[2] = (unsigned long)(arg2); \
4187 _argvec[3] = (unsigned long)(arg3); \
4188 _argvec[4] = (unsigned long)(arg4); \
4189 _argvec[5] = (unsigned long)(arg5); \
4190 _argvec[6] = (unsigned long)(arg6); \
4191 _argvec[7] = (unsigned long)(arg7); \
4192 _argvec[8] = (unsigned long)(arg8); \
4193 _argvec[9] = (unsigned long)(arg9); \
4194 _argvec[10] = (unsigned long)(arg10); \
4195 _argvec[11] = (unsigned long)(arg11); \
4196 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00004197 VALGRIND_ALIGN_STACK \
4198 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00004199 "ldr r0, [%1, #40] \n\t" \
4200 "ldr r1, [%1, #44] \n\t" \
4201 "push {r0, r1} \n\t" \
4202 "ldr r0, [%1, #20] \n\t" \
4203 "ldr r1, [%1, #24] \n\t" \
4204 "ldr r2, [%1, #28] \n\t" \
4205 "ldr r3, [%1, #32] \n\t" \
4206 "ldr r4, [%1, #36] \n\t" \
4207 "push {r0, r1, r2, r3, r4} \n\t" \
4208 "ldr r0, [%1, #4] \n\t" \
4209 "ldr r1, [%1, #8] \n\t" \
4210 "ldr r2, [%1, #12] \n\t" \
4211 "ldr r3, [%1, #16] \n\t" \
4212 "ldr r4, [%1] \n\t" /* target->r4 */ \
4213 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00004214 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00004215 "mov %0, r0" \
4216 : /*out*/ "=r" (_res) \
4217 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00004218 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00004219 ); \
4220 lval = (__typeof__(lval)) _res; \
4221 } while (0)
4222
4223#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
4224 arg6,arg7,arg8,arg9,arg10, \
4225 arg11,arg12) \
4226 do { \
4227 volatile OrigFn _orig = (orig); \
4228 volatile unsigned long _argvec[13]; \
4229 volatile unsigned long _res; \
4230 _argvec[0] = (unsigned long)_orig.nraddr; \
4231 _argvec[1] = (unsigned long)(arg1); \
4232 _argvec[2] = (unsigned long)(arg2); \
4233 _argvec[3] = (unsigned long)(arg3); \
4234 _argvec[4] = (unsigned long)(arg4); \
4235 _argvec[5] = (unsigned long)(arg5); \
4236 _argvec[6] = (unsigned long)(arg6); \
4237 _argvec[7] = (unsigned long)(arg7); \
4238 _argvec[8] = (unsigned long)(arg8); \
4239 _argvec[9] = (unsigned long)(arg9); \
4240 _argvec[10] = (unsigned long)(arg10); \
4241 _argvec[11] = (unsigned long)(arg11); \
4242 _argvec[12] = (unsigned long)(arg12); \
4243 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00004244 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00004245 "ldr r0, [%1, #40] \n\t" \
4246 "ldr r1, [%1, #44] \n\t" \
4247 "ldr r2, [%1, #48] \n\t" \
4248 "push {r0, r1, r2} \n\t" \
4249 "ldr r0, [%1, #20] \n\t" \
4250 "ldr r1, [%1, #24] \n\t" \
4251 "ldr r2, [%1, #28] \n\t" \
4252 "ldr r3, [%1, #32] \n\t" \
4253 "ldr r4, [%1, #36] \n\t" \
4254 "push {r0, r1, r2, r3, r4} \n\t" \
4255 "ldr r0, [%1, #4] \n\t" \
4256 "ldr r1, [%1, #8] \n\t" \
4257 "ldr r2, [%1, #12] \n\t" \
4258 "ldr r3, [%1, #16] \n\t" \
4259 "ldr r4, [%1] \n\t" /* target->r4 */ \
4260 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00004261 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00004262 "mov %0, r0" \
4263 : /*out*/ "=r" (_res) \
4264 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00004265 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00004266 ); \
4267 lval = (__typeof__(lval)) _res; \
4268 } while (0)
4269
4270#endif /* PLAT_arm_linux */
4271
sewardjf0c12502014-01-12 12:54:00 +00004272/* ------------------------ arm64-linux ------------------------ */
4273
4274#if defined(PLAT_arm64_linux)
4275
4276/* These regs are trashed by the hidden call. */
4277#define __CALLER_SAVED_REGS \
4278 "x0", "x1", "x2", "x3","x4", "x5", "x6", "x7", "x8", "x9", \
4279 "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", \
sewardjbb9b1b92014-03-09 09:46:04 +00004280 "x18", "x19", "x20", "x30", \
sewardjf0c12502014-01-12 12:54:00 +00004281 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \
4282 "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", \
4283 "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", \
4284 "v26", "v27", "v28", "v29", "v30", "v31"
4285
sewardjbb9b1b92014-03-09 09:46:04 +00004286/* x21 is callee-saved, so we can use it to save and restore SP around
4287 the hidden call. */
4288#define VALGRIND_ALIGN_STACK \
4289 "mov x21, sp\n\t" \
4290 "bic sp, x21, #15\n\t"
4291#define VALGRIND_RESTORE_STACK \
4292 "mov sp, x21\n\t"
sewardjf0c12502014-01-12 12:54:00 +00004293
4294/* These CALL_FN_ macros assume that on arm64-linux,
4295 sizeof(unsigned long) == 8. */
4296
4297#define CALL_FN_W_v(lval, orig) \
4298 do { \
4299 volatile OrigFn _orig = (orig); \
4300 volatile unsigned long _argvec[1]; \
4301 volatile unsigned long _res; \
4302 _argvec[0] = (unsigned long)_orig.nraddr; \
4303 __asm__ volatile( \
4304 VALGRIND_ALIGN_STACK \
4305 "ldr x8, [%1] \n\t" /* target->x8 */ \
4306 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4307 VALGRIND_RESTORE_STACK \
4308 "mov %0, x0\n" \
4309 : /*out*/ "=r" (_res) \
4310 : /*in*/ "0" (&_argvec[0]) \
sewardjbb9b1b92014-03-09 09:46:04 +00004311 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00004312 ); \
4313 lval = (__typeof__(lval)) _res; \
4314 } while (0)
4315
4316#define CALL_FN_W_W(lval, orig, arg1) \
4317 do { \
4318 volatile OrigFn _orig = (orig); \
4319 volatile unsigned long _argvec[2]; \
4320 volatile unsigned long _res; \
4321 _argvec[0] = (unsigned long)_orig.nraddr; \
4322 _argvec[1] = (unsigned long)(arg1); \
4323 __asm__ volatile( \
4324 VALGRIND_ALIGN_STACK \
4325 "ldr x0, [%1, #8] \n\t" \
4326 "ldr x8, [%1] \n\t" /* target->x8 */ \
4327 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4328 VALGRIND_RESTORE_STACK \
4329 "mov %0, x0\n" \
4330 : /*out*/ "=r" (_res) \
4331 : /*in*/ "0" (&_argvec[0]) \
sewardjbb9b1b92014-03-09 09:46:04 +00004332 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00004333 ); \
4334 lval = (__typeof__(lval)) _res; \
4335 } while (0)
4336
4337#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
4338 do { \
4339 volatile OrigFn _orig = (orig); \
4340 volatile unsigned long _argvec[3]; \
4341 volatile unsigned long _res; \
4342 _argvec[0] = (unsigned long)_orig.nraddr; \
4343 _argvec[1] = (unsigned long)(arg1); \
4344 _argvec[2] = (unsigned long)(arg2); \
4345 __asm__ volatile( \
4346 VALGRIND_ALIGN_STACK \
4347 "ldr x0, [%1, #8] \n\t" \
4348 "ldr x1, [%1, #16] \n\t" \
4349 "ldr x8, [%1] \n\t" /* target->x8 */ \
4350 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4351 VALGRIND_RESTORE_STACK \
4352 "mov %0, x0\n" \
4353 : /*out*/ "=r" (_res) \
4354 : /*in*/ "0" (&_argvec[0]) \
sewardj91e14602014-03-16 14:21:41 +00004355 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00004356 ); \
4357 lval = (__typeof__(lval)) _res; \
4358 } while (0)
4359
4360#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
4361 do { \
4362 volatile OrigFn _orig = (orig); \
4363 volatile unsigned long _argvec[4]; \
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 __asm__ volatile( \
4370 VALGRIND_ALIGN_STACK \
4371 "ldr x0, [%1, #8] \n\t" \
4372 "ldr x1, [%1, #16] \n\t" \
4373 "ldr x2, [%1, #24] \n\t" \
4374 "ldr x8, [%1] \n\t" /* target->x8 */ \
4375 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4376 VALGRIND_RESTORE_STACK \
4377 "mov %0, x0\n" \
4378 : /*out*/ "=r" (_res) \
4379 : /*in*/ "0" (&_argvec[0]) \
sewardj91e14602014-03-16 14:21:41 +00004380 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00004381 ); \
4382 lval = (__typeof__(lval)) _res; \
4383 } while (0)
4384
4385#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
4386 do { \
4387 volatile OrigFn _orig = (orig); \
4388 volatile unsigned long _argvec[5]; \
4389 volatile unsigned long _res; \
4390 _argvec[0] = (unsigned long)_orig.nraddr; \
4391 _argvec[1] = (unsigned long)(arg1); \
4392 _argvec[2] = (unsigned long)(arg2); \
4393 _argvec[3] = (unsigned long)(arg3); \
4394 _argvec[4] = (unsigned long)(arg4); \
4395 __asm__ volatile( \
4396 VALGRIND_ALIGN_STACK \
4397 "ldr x0, [%1, #8] \n\t" \
4398 "ldr x1, [%1, #16] \n\t" \
4399 "ldr x2, [%1, #24] \n\t" \
4400 "ldr x3, [%1, #32] \n\t" \
4401 "ldr x8, [%1] \n\t" /* target->x8 */ \
4402 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4403 VALGRIND_RESTORE_STACK \
4404 "mov %0, x0" \
4405 : /*out*/ "=r" (_res) \
4406 : /*in*/ "0" (&_argvec[0]) \
sewardj91e14602014-03-16 14:21:41 +00004407 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4408 ); \
4409 lval = (__typeof__(lval)) _res; \
4410 } while (0)
4411
4412#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
4413 do { \
4414 volatile OrigFn _orig = (orig); \
4415 volatile unsigned long _argvec[6]; \
4416 volatile unsigned long _res; \
4417 _argvec[0] = (unsigned long)_orig.nraddr; \
4418 _argvec[1] = (unsigned long)(arg1); \
4419 _argvec[2] = (unsigned long)(arg2); \
4420 _argvec[3] = (unsigned long)(arg3); \
4421 _argvec[4] = (unsigned long)(arg4); \
4422 _argvec[5] = (unsigned long)(arg5); \
4423 __asm__ volatile( \
4424 VALGRIND_ALIGN_STACK \
4425 "ldr x0, [%1, #8] \n\t" \
4426 "ldr x1, [%1, #16] \n\t" \
4427 "ldr x2, [%1, #24] \n\t" \
4428 "ldr x3, [%1, #32] \n\t" \
4429 "ldr x4, [%1, #40] \n\t" \
4430 "ldr x8, [%1] \n\t" /* target->x8 */ \
4431 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4432 VALGRIND_RESTORE_STACK \
4433 "mov %0, x0" \
4434 : /*out*/ "=r" (_res) \
4435 : /*in*/ "0" (&_argvec[0]) \
4436 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4437 ); \
4438 lval = (__typeof__(lval)) _res; \
4439 } while (0)
4440
4441#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
4442 do { \
4443 volatile OrigFn _orig = (orig); \
4444 volatile unsigned long _argvec[7]; \
4445 volatile unsigned long _res; \
4446 _argvec[0] = (unsigned long)_orig.nraddr; \
4447 _argvec[1] = (unsigned long)(arg1); \
4448 _argvec[2] = (unsigned long)(arg2); \
4449 _argvec[3] = (unsigned long)(arg3); \
4450 _argvec[4] = (unsigned long)(arg4); \
4451 _argvec[5] = (unsigned long)(arg5); \
4452 _argvec[6] = (unsigned long)(arg6); \
4453 __asm__ volatile( \
4454 VALGRIND_ALIGN_STACK \
4455 "ldr x0, [%1, #8] \n\t" \
4456 "ldr x1, [%1, #16] \n\t" \
4457 "ldr x2, [%1, #24] \n\t" \
4458 "ldr x3, [%1, #32] \n\t" \
4459 "ldr x4, [%1, #40] \n\t" \
4460 "ldr x5, [%1, #48] \n\t" \
4461 "ldr x8, [%1] \n\t" /* target->x8 */ \
4462 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4463 VALGRIND_RESTORE_STACK \
4464 "mov %0, x0" \
4465 : /*out*/ "=r" (_res) \
4466 : /*in*/ "0" (&_argvec[0]) \
4467 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4468 ); \
4469 lval = (__typeof__(lval)) _res; \
4470 } while (0)
4471
4472#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4473 arg7) \
4474 do { \
4475 volatile OrigFn _orig = (orig); \
4476 volatile unsigned long _argvec[8]; \
4477 volatile unsigned long _res; \
4478 _argvec[0] = (unsigned long)_orig.nraddr; \
4479 _argvec[1] = (unsigned long)(arg1); \
4480 _argvec[2] = (unsigned long)(arg2); \
4481 _argvec[3] = (unsigned long)(arg3); \
4482 _argvec[4] = (unsigned long)(arg4); \
4483 _argvec[5] = (unsigned long)(arg5); \
4484 _argvec[6] = (unsigned long)(arg6); \
4485 _argvec[7] = (unsigned long)(arg7); \
4486 __asm__ volatile( \
4487 VALGRIND_ALIGN_STACK \
4488 "ldr x0, [%1, #8] \n\t" \
4489 "ldr x1, [%1, #16] \n\t" \
4490 "ldr x2, [%1, #24] \n\t" \
4491 "ldr x3, [%1, #32] \n\t" \
4492 "ldr x4, [%1, #40] \n\t" \
4493 "ldr x5, [%1, #48] \n\t" \
4494 "ldr x6, [%1, #56] \n\t" \
4495 "ldr x8, [%1] \n\t" /* target->x8 */ \
4496 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4497 VALGRIND_RESTORE_STACK \
4498 "mov %0, x0" \
4499 : /*out*/ "=r" (_res) \
4500 : /*in*/ "0" (&_argvec[0]) \
4501 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4502 ); \
4503 lval = (__typeof__(lval)) _res; \
4504 } while (0)
4505
4506#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4507 arg7,arg8) \
4508 do { \
4509 volatile OrigFn _orig = (orig); \
4510 volatile unsigned long _argvec[9]; \
4511 volatile unsigned long _res; \
4512 _argvec[0] = (unsigned long)_orig.nraddr; \
4513 _argvec[1] = (unsigned long)(arg1); \
4514 _argvec[2] = (unsigned long)(arg2); \
4515 _argvec[3] = (unsigned long)(arg3); \
4516 _argvec[4] = (unsigned long)(arg4); \
4517 _argvec[5] = (unsigned long)(arg5); \
4518 _argvec[6] = (unsigned long)(arg6); \
4519 _argvec[7] = (unsigned long)(arg7); \
4520 _argvec[8] = (unsigned long)(arg8); \
4521 __asm__ volatile( \
4522 VALGRIND_ALIGN_STACK \
4523 "ldr x0, [%1, #8] \n\t" \
4524 "ldr x1, [%1, #16] \n\t" \
4525 "ldr x2, [%1, #24] \n\t" \
4526 "ldr x3, [%1, #32] \n\t" \
4527 "ldr x4, [%1, #40] \n\t" \
4528 "ldr x5, [%1, #48] \n\t" \
4529 "ldr x6, [%1, #56] \n\t" \
4530 "ldr x7, [%1, #64] \n\t" \
4531 "ldr x8, [%1] \n\t" /* target->x8 */ \
4532 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4533 VALGRIND_RESTORE_STACK \
4534 "mov %0, x0" \
4535 : /*out*/ "=r" (_res) \
4536 : /*in*/ "0" (&_argvec[0]) \
4537 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4538 ); \
4539 lval = (__typeof__(lval)) _res; \
4540 } while (0)
4541
4542#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4543 arg7,arg8,arg9) \
4544 do { \
4545 volatile OrigFn _orig = (orig); \
4546 volatile unsigned long _argvec[10]; \
4547 volatile unsigned long _res; \
4548 _argvec[0] = (unsigned long)_orig.nraddr; \
4549 _argvec[1] = (unsigned long)(arg1); \
4550 _argvec[2] = (unsigned long)(arg2); \
4551 _argvec[3] = (unsigned long)(arg3); \
4552 _argvec[4] = (unsigned long)(arg4); \
4553 _argvec[5] = (unsigned long)(arg5); \
4554 _argvec[6] = (unsigned long)(arg6); \
4555 _argvec[7] = (unsigned long)(arg7); \
4556 _argvec[8] = (unsigned long)(arg8); \
4557 _argvec[9] = (unsigned long)(arg9); \
4558 __asm__ volatile( \
4559 VALGRIND_ALIGN_STACK \
4560 "sub sp, sp, #0x20 \n\t" \
4561 "ldr x0, [%1, #8] \n\t" \
4562 "ldr x1, [%1, #16] \n\t" \
4563 "ldr x2, [%1, #24] \n\t" \
4564 "ldr x3, [%1, #32] \n\t" \
4565 "ldr x4, [%1, #40] \n\t" \
4566 "ldr x5, [%1, #48] \n\t" \
4567 "ldr x6, [%1, #56] \n\t" \
4568 "ldr x7, [%1, #64] \n\t" \
4569 "ldr x8, [%1, #72] \n\t" \
4570 "str x8, [sp, #0] \n\t" \
4571 "ldr x8, [%1] \n\t" /* target->x8 */ \
4572 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4573 VALGRIND_RESTORE_STACK \
4574 "mov %0, x0" \
4575 : /*out*/ "=r" (_res) \
4576 : /*in*/ "0" (&_argvec[0]) \
4577 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4578 ); \
4579 lval = (__typeof__(lval)) _res; \
4580 } while (0)
4581
4582#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4583 arg7,arg8,arg9,arg10) \
4584 do { \
4585 volatile OrigFn _orig = (orig); \
4586 volatile unsigned long _argvec[11]; \
4587 volatile unsigned long _res; \
4588 _argvec[0] = (unsigned long)_orig.nraddr; \
4589 _argvec[1] = (unsigned long)(arg1); \
4590 _argvec[2] = (unsigned long)(arg2); \
4591 _argvec[3] = (unsigned long)(arg3); \
4592 _argvec[4] = (unsigned long)(arg4); \
4593 _argvec[5] = (unsigned long)(arg5); \
4594 _argvec[6] = (unsigned long)(arg6); \
4595 _argvec[7] = (unsigned long)(arg7); \
4596 _argvec[8] = (unsigned long)(arg8); \
4597 _argvec[9] = (unsigned long)(arg9); \
4598 _argvec[10] = (unsigned long)(arg10); \
4599 __asm__ volatile( \
4600 VALGRIND_ALIGN_STACK \
4601 "sub sp, sp, #0x20 \n\t" \
4602 "ldr x0, [%1, #8] \n\t" \
4603 "ldr x1, [%1, #16] \n\t" \
4604 "ldr x2, [%1, #24] \n\t" \
4605 "ldr x3, [%1, #32] \n\t" \
4606 "ldr x4, [%1, #40] \n\t" \
4607 "ldr x5, [%1, #48] \n\t" \
4608 "ldr x6, [%1, #56] \n\t" \
4609 "ldr x7, [%1, #64] \n\t" \
4610 "ldr x8, [%1, #72] \n\t" \
4611 "str x8, [sp, #0] \n\t" \
4612 "ldr x8, [%1, #80] \n\t" \
4613 "str x8, [sp, #8] \n\t" \
4614 "ldr x8, [%1] \n\t" /* target->x8 */ \
4615 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4616 VALGRIND_RESTORE_STACK \
4617 "mov %0, x0" \
4618 : /*out*/ "=r" (_res) \
4619 : /*in*/ "0" (&_argvec[0]) \
4620 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4621 ); \
4622 lval = (__typeof__(lval)) _res; \
4623 } while (0)
4624
4625#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4626 arg7,arg8,arg9,arg10,arg11) \
4627 do { \
4628 volatile OrigFn _orig = (orig); \
4629 volatile unsigned long _argvec[12]; \
4630 volatile unsigned long _res; \
4631 _argvec[0] = (unsigned long)_orig.nraddr; \
4632 _argvec[1] = (unsigned long)(arg1); \
4633 _argvec[2] = (unsigned long)(arg2); \
4634 _argvec[3] = (unsigned long)(arg3); \
4635 _argvec[4] = (unsigned long)(arg4); \
4636 _argvec[5] = (unsigned long)(arg5); \
4637 _argvec[6] = (unsigned long)(arg6); \
4638 _argvec[7] = (unsigned long)(arg7); \
4639 _argvec[8] = (unsigned long)(arg8); \
4640 _argvec[9] = (unsigned long)(arg9); \
4641 _argvec[10] = (unsigned long)(arg10); \
4642 _argvec[11] = (unsigned long)(arg11); \
4643 __asm__ volatile( \
4644 VALGRIND_ALIGN_STACK \
4645 "sub sp, sp, #0x30 \n\t" \
4646 "ldr x0, [%1, #8] \n\t" \
4647 "ldr x1, [%1, #16] \n\t" \
4648 "ldr x2, [%1, #24] \n\t" \
4649 "ldr x3, [%1, #32] \n\t" \
4650 "ldr x4, [%1, #40] \n\t" \
4651 "ldr x5, [%1, #48] \n\t" \
4652 "ldr x6, [%1, #56] \n\t" \
4653 "ldr x7, [%1, #64] \n\t" \
4654 "ldr x8, [%1, #72] \n\t" \
4655 "str x8, [sp, #0] \n\t" \
4656 "ldr x8, [%1, #80] \n\t" \
4657 "str x8, [sp, #8] \n\t" \
4658 "ldr x8, [%1, #88] \n\t" \
4659 "str x8, [sp, #16] \n\t" \
4660 "ldr x8, [%1] \n\t" /* target->x8 */ \
4661 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4662 VALGRIND_RESTORE_STACK \
4663 "mov %0, x0" \
4664 : /*out*/ "=r" (_res) \
4665 : /*in*/ "0" (&_argvec[0]) \
4666 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
4667 ); \
4668 lval = (__typeof__(lval)) _res; \
4669 } while (0)
4670
4671#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4672 arg7,arg8,arg9,arg10,arg11, \
4673 arg12) \
4674 do { \
4675 volatile OrigFn _orig = (orig); \
4676 volatile unsigned long _argvec[13]; \
4677 volatile unsigned long _res; \
4678 _argvec[0] = (unsigned long)_orig.nraddr; \
4679 _argvec[1] = (unsigned long)(arg1); \
4680 _argvec[2] = (unsigned long)(arg2); \
4681 _argvec[3] = (unsigned long)(arg3); \
4682 _argvec[4] = (unsigned long)(arg4); \
4683 _argvec[5] = (unsigned long)(arg5); \
4684 _argvec[6] = (unsigned long)(arg6); \
4685 _argvec[7] = (unsigned long)(arg7); \
4686 _argvec[8] = (unsigned long)(arg8); \
4687 _argvec[9] = (unsigned long)(arg9); \
4688 _argvec[10] = (unsigned long)(arg10); \
4689 _argvec[11] = (unsigned long)(arg11); \
4690 _argvec[12] = (unsigned long)(arg12); \
4691 __asm__ volatile( \
4692 VALGRIND_ALIGN_STACK \
4693 "sub sp, sp, #0x30 \n\t" \
4694 "ldr x0, [%1, #8] \n\t" \
4695 "ldr x1, [%1, #16] \n\t" \
4696 "ldr x2, [%1, #24] \n\t" \
4697 "ldr x3, [%1, #32] \n\t" \
4698 "ldr x4, [%1, #40] \n\t" \
4699 "ldr x5, [%1, #48] \n\t" \
4700 "ldr x6, [%1, #56] \n\t" \
4701 "ldr x7, [%1, #64] \n\t" \
4702 "ldr x8, [%1, #72] \n\t" \
4703 "str x8, [sp, #0] \n\t" \
4704 "ldr x8, [%1, #80] \n\t" \
4705 "str x8, [sp, #8] \n\t" \
4706 "ldr x8, [%1, #88] \n\t" \
4707 "str x8, [sp, #16] \n\t" \
4708 "ldr x8, [%1, #96] \n\t" \
4709 "str x8, [sp, #24] \n\t" \
4710 "ldr x8, [%1] \n\t" /* target->x8 */ \
4711 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
4712 VALGRIND_RESTORE_STACK \
4713 "mov %0, x0" \
4714 : /*out*/ "=r" (_res) \
4715 : /*in*/ "0" (&_argvec[0]) \
4716 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
sewardjf0c12502014-01-12 12:54:00 +00004717 ); \
4718 lval = (__typeof__(lval)) _res; \
4719 } while (0)
4720
4721#endif /* PLAT_arm64_linux */
4722
sewardjb5b87402011-03-07 16:05:35 +00004723/* ------------------------- s390x-linux ------------------------- */
4724
4725#if defined(PLAT_s390x_linux)
4726
4727/* Similar workaround as amd64 (see above), but we use r11 as frame
4728 pointer and save the old r11 in r7. r11 might be used for
4729 argvec, therefore we copy argvec in r1 since r1 is clobbered
4730 after the call anyway. */
4731#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
4732# define __FRAME_POINTER \
4733 ,"d"(__builtin_dwarf_cfa())
4734# define VALGRIND_CFI_PROLOGUE \
4735 ".cfi_remember_state\n\t" \
4736 "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */ \
4737 "lgr 7,11\n\t" \
4738 "lgr 11,%2\n\t" \
4739 ".cfi_def_cfa r11, 0\n\t"
4740# define VALGRIND_CFI_EPILOGUE \
4741 "lgr 11, 7\n\t" \
4742 ".cfi_restore_state\n\t"
4743#else
4744# define __FRAME_POINTER
4745# define VALGRIND_CFI_PROLOGUE \
4746 "lgr 1,%1\n\t"
4747# define VALGRIND_CFI_EPILOGUE
4748#endif
4749
florian9af940f2012-08-03 03:21:42 +00004750/* Nb: On s390 the stack pointer is properly aligned *at all times*
4751 according to the s390 GCC maintainer. (The ABI specification is not
4752 precise in this regard.) Therefore, VALGRIND_ALIGN_STACK and
4753 VALGRIND_RESTORE_STACK are not defined here. */
sewardjb5b87402011-03-07 16:05:35 +00004754
4755/* These regs are trashed by the hidden call. Note that we overwrite
4756 r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
4757 function a proper return address. All others are ABI defined call
4758 clobbers. */
4759#define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \
4760 "f0","f1","f2","f3","f4","f5","f6","f7"
4761
florian9af940f2012-08-03 03:21:42 +00004762/* Nb: Although r11 is modified in the asm snippets below (inside
4763 VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for
4764 two reasons:
4765 (1) r11 is restored in VALGRIND_CFI_EPILOGUE, so effectively it is not
4766 modified
4767 (2) GCC will complain that r11 cannot appear inside a clobber section,
4768 when compiled with -O -fno-omit-frame-pointer
4769 */
sewardjb5b87402011-03-07 16:05:35 +00004770
4771#define CALL_FN_W_v(lval, orig) \
4772 do { \
4773 volatile OrigFn _orig = (orig); \
4774 volatile unsigned long _argvec[1]; \
4775 volatile unsigned long _res; \
4776 _argvec[0] = (unsigned long)_orig.nraddr; \
4777 __asm__ volatile( \
4778 VALGRIND_CFI_PROLOGUE \
4779 "aghi 15,-160\n\t" \
4780 "lg 1, 0(1)\n\t" /* target->r1 */ \
4781 VALGRIND_CALL_NOREDIR_R1 \
4782 "lgr %0, 2\n\t" \
4783 "aghi 15,160\n\t" \
4784 VALGRIND_CFI_EPILOGUE \
4785 : /*out*/ "=d" (_res) \
4786 : /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \
4787 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4788 ); \
4789 lval = (__typeof__(lval)) _res; \
4790 } while (0)
4791
4792/* The call abi has the arguments in r2-r6 and stack */
4793#define CALL_FN_W_W(lval, orig, arg1) \
4794 do { \
4795 volatile OrigFn _orig = (orig); \
4796 volatile unsigned long _argvec[2]; \
4797 volatile unsigned long _res; \
4798 _argvec[0] = (unsigned long)_orig.nraddr; \
4799 _argvec[1] = (unsigned long)arg1; \
4800 __asm__ volatile( \
4801 VALGRIND_CFI_PROLOGUE \
4802 "aghi 15,-160\n\t" \
4803 "lg 2, 8(1)\n\t" \
4804 "lg 1, 0(1)\n\t" \
4805 VALGRIND_CALL_NOREDIR_R1 \
4806 "lgr %0, 2\n\t" \
4807 "aghi 15,160\n\t" \
4808 VALGRIND_CFI_EPILOGUE \
4809 : /*out*/ "=d" (_res) \
4810 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4811 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4812 ); \
4813 lval = (__typeof__(lval)) _res; \
4814 } while (0)
4815
4816#define CALL_FN_W_WW(lval, orig, arg1, arg2) \
4817 do { \
4818 volatile OrigFn _orig = (orig); \
4819 volatile unsigned long _argvec[3]; \
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 __asm__ volatile( \
4825 VALGRIND_CFI_PROLOGUE \
4826 "aghi 15,-160\n\t" \
4827 "lg 2, 8(1)\n\t" \
4828 "lg 3,16(1)\n\t" \
4829 "lg 1, 0(1)\n\t" \
4830 VALGRIND_CALL_NOREDIR_R1 \
4831 "lgr %0, 2\n\t" \
4832 "aghi 15,160\n\t" \
4833 VALGRIND_CFI_EPILOGUE \
4834 : /*out*/ "=d" (_res) \
4835 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4836 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4837 ); \
4838 lval = (__typeof__(lval)) _res; \
4839 } while (0)
4840
4841#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \
4842 do { \
4843 volatile OrigFn _orig = (orig); \
4844 volatile unsigned long _argvec[4]; \
4845 volatile unsigned long _res; \
4846 _argvec[0] = (unsigned long)_orig.nraddr; \
4847 _argvec[1] = (unsigned long)arg1; \
4848 _argvec[2] = (unsigned long)arg2; \
4849 _argvec[3] = (unsigned long)arg3; \
4850 __asm__ volatile( \
4851 VALGRIND_CFI_PROLOGUE \
4852 "aghi 15,-160\n\t" \
4853 "lg 2, 8(1)\n\t" \
4854 "lg 3,16(1)\n\t" \
4855 "lg 4,24(1)\n\t" \
4856 "lg 1, 0(1)\n\t" \
4857 VALGRIND_CALL_NOREDIR_R1 \
4858 "lgr %0, 2\n\t" \
4859 "aghi 15,160\n\t" \
4860 VALGRIND_CFI_EPILOGUE \
4861 : /*out*/ "=d" (_res) \
4862 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4863 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4864 ); \
4865 lval = (__typeof__(lval)) _res; \
4866 } while (0)
4867
4868#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \
4869 do { \
4870 volatile OrigFn _orig = (orig); \
4871 volatile unsigned long _argvec[5]; \
4872 volatile unsigned long _res; \
4873 _argvec[0] = (unsigned long)_orig.nraddr; \
4874 _argvec[1] = (unsigned long)arg1; \
4875 _argvec[2] = (unsigned long)arg2; \
4876 _argvec[3] = (unsigned long)arg3; \
4877 _argvec[4] = (unsigned long)arg4; \
4878 __asm__ volatile( \
4879 VALGRIND_CFI_PROLOGUE \
4880 "aghi 15,-160\n\t" \
4881 "lg 2, 8(1)\n\t" \
4882 "lg 3,16(1)\n\t" \
4883 "lg 4,24(1)\n\t" \
4884 "lg 5,32(1)\n\t" \
4885 "lg 1, 0(1)\n\t" \
4886 VALGRIND_CALL_NOREDIR_R1 \
4887 "lgr %0, 2\n\t" \
4888 "aghi 15,160\n\t" \
4889 VALGRIND_CFI_EPILOGUE \
4890 : /*out*/ "=d" (_res) \
4891 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4892 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
4893 ); \
4894 lval = (__typeof__(lval)) _res; \
4895 } while (0)
4896
4897#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \
4898 do { \
4899 volatile OrigFn _orig = (orig); \
4900 volatile unsigned long _argvec[6]; \
4901 volatile unsigned long _res; \
4902 _argvec[0] = (unsigned long)_orig.nraddr; \
4903 _argvec[1] = (unsigned long)arg1; \
4904 _argvec[2] = (unsigned long)arg2; \
4905 _argvec[3] = (unsigned long)arg3; \
4906 _argvec[4] = (unsigned long)arg4; \
4907 _argvec[5] = (unsigned long)arg5; \
4908 __asm__ volatile( \
4909 VALGRIND_CFI_PROLOGUE \
4910 "aghi 15,-160\n\t" \
4911 "lg 2, 8(1)\n\t" \
4912 "lg 3,16(1)\n\t" \
4913 "lg 4,24(1)\n\t" \
4914 "lg 5,32(1)\n\t" \
4915 "lg 6,40(1)\n\t" \
4916 "lg 1, 0(1)\n\t" \
4917 VALGRIND_CALL_NOREDIR_R1 \
4918 "lgr %0, 2\n\t" \
4919 "aghi 15,160\n\t" \
4920 VALGRIND_CFI_EPILOGUE \
4921 : /*out*/ "=d" (_res) \
4922 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4923 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4924 ); \
4925 lval = (__typeof__(lval)) _res; \
4926 } while (0)
4927
4928#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4929 arg6) \
4930 do { \
4931 volatile OrigFn _orig = (orig); \
4932 volatile unsigned long _argvec[7]; \
4933 volatile unsigned long _res; \
4934 _argvec[0] = (unsigned long)_orig.nraddr; \
4935 _argvec[1] = (unsigned long)arg1; \
4936 _argvec[2] = (unsigned long)arg2; \
4937 _argvec[3] = (unsigned long)arg3; \
4938 _argvec[4] = (unsigned long)arg4; \
4939 _argvec[5] = (unsigned long)arg5; \
4940 _argvec[6] = (unsigned long)arg6; \
4941 __asm__ volatile( \
4942 VALGRIND_CFI_PROLOGUE \
4943 "aghi 15,-168\n\t" \
4944 "lg 2, 8(1)\n\t" \
4945 "lg 3,16(1)\n\t" \
4946 "lg 4,24(1)\n\t" \
4947 "lg 5,32(1)\n\t" \
4948 "lg 6,40(1)\n\t" \
4949 "mvc 160(8,15), 48(1)\n\t" \
4950 "lg 1, 0(1)\n\t" \
4951 VALGRIND_CALL_NOREDIR_R1 \
4952 "lgr %0, 2\n\t" \
4953 "aghi 15,168\n\t" \
4954 VALGRIND_CFI_EPILOGUE \
4955 : /*out*/ "=d" (_res) \
4956 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4957 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4958 ); \
4959 lval = (__typeof__(lval)) _res; \
4960 } while (0)
4961
4962#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4963 arg6, arg7) \
4964 do { \
4965 volatile OrigFn _orig = (orig); \
4966 volatile unsigned long _argvec[8]; \
4967 volatile unsigned long _res; \
4968 _argvec[0] = (unsigned long)_orig.nraddr; \
4969 _argvec[1] = (unsigned long)arg1; \
4970 _argvec[2] = (unsigned long)arg2; \
4971 _argvec[3] = (unsigned long)arg3; \
4972 _argvec[4] = (unsigned long)arg4; \
4973 _argvec[5] = (unsigned long)arg5; \
4974 _argvec[6] = (unsigned long)arg6; \
4975 _argvec[7] = (unsigned long)arg7; \
4976 __asm__ volatile( \
4977 VALGRIND_CFI_PROLOGUE \
4978 "aghi 15,-176\n\t" \
4979 "lg 2, 8(1)\n\t" \
4980 "lg 3,16(1)\n\t" \
4981 "lg 4,24(1)\n\t" \
4982 "lg 5,32(1)\n\t" \
4983 "lg 6,40(1)\n\t" \
4984 "mvc 160(8,15), 48(1)\n\t" \
4985 "mvc 168(8,15), 56(1)\n\t" \
4986 "lg 1, 0(1)\n\t" \
4987 VALGRIND_CALL_NOREDIR_R1 \
4988 "lgr %0, 2\n\t" \
4989 "aghi 15,176\n\t" \
4990 VALGRIND_CFI_EPILOGUE \
4991 : /*out*/ "=d" (_res) \
4992 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
4993 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4994 ); \
4995 lval = (__typeof__(lval)) _res; \
4996 } while (0)
4997
4998#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
4999 arg6, arg7 ,arg8) \
5000 do { \
5001 volatile OrigFn _orig = (orig); \
5002 volatile unsigned long _argvec[9]; \
5003 volatile unsigned long _res; \
5004 _argvec[0] = (unsigned long)_orig.nraddr; \
5005 _argvec[1] = (unsigned long)arg1; \
5006 _argvec[2] = (unsigned long)arg2; \
5007 _argvec[3] = (unsigned long)arg3; \
5008 _argvec[4] = (unsigned long)arg4; \
5009 _argvec[5] = (unsigned long)arg5; \
5010 _argvec[6] = (unsigned long)arg6; \
5011 _argvec[7] = (unsigned long)arg7; \
5012 _argvec[8] = (unsigned long)arg8; \
5013 __asm__ volatile( \
5014 VALGRIND_CFI_PROLOGUE \
5015 "aghi 15,-184\n\t" \
5016 "lg 2, 8(1)\n\t" \
5017 "lg 3,16(1)\n\t" \
5018 "lg 4,24(1)\n\t" \
5019 "lg 5,32(1)\n\t" \
5020 "lg 6,40(1)\n\t" \
5021 "mvc 160(8,15), 48(1)\n\t" \
5022 "mvc 168(8,15), 56(1)\n\t" \
5023 "mvc 176(8,15), 64(1)\n\t" \
5024 "lg 1, 0(1)\n\t" \
5025 VALGRIND_CALL_NOREDIR_R1 \
5026 "lgr %0, 2\n\t" \
5027 "aghi 15,184\n\t" \
5028 VALGRIND_CFI_EPILOGUE \
5029 : /*out*/ "=d" (_res) \
5030 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
5031 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5032 ); \
5033 lval = (__typeof__(lval)) _res; \
5034 } while (0)
5035
5036#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
5037 arg6, arg7 ,arg8, arg9) \
5038 do { \
5039 volatile OrigFn _orig = (orig); \
5040 volatile unsigned long _argvec[10]; \
5041 volatile unsigned long _res; \
5042 _argvec[0] = (unsigned long)_orig.nraddr; \
5043 _argvec[1] = (unsigned long)arg1; \
5044 _argvec[2] = (unsigned long)arg2; \
5045 _argvec[3] = (unsigned long)arg3; \
5046 _argvec[4] = (unsigned long)arg4; \
5047 _argvec[5] = (unsigned long)arg5; \
5048 _argvec[6] = (unsigned long)arg6; \
5049 _argvec[7] = (unsigned long)arg7; \
5050 _argvec[8] = (unsigned long)arg8; \
5051 _argvec[9] = (unsigned long)arg9; \
5052 __asm__ volatile( \
5053 VALGRIND_CFI_PROLOGUE \
5054 "aghi 15,-192\n\t" \
5055 "lg 2, 8(1)\n\t" \
5056 "lg 3,16(1)\n\t" \
5057 "lg 4,24(1)\n\t" \
5058 "lg 5,32(1)\n\t" \
5059 "lg 6,40(1)\n\t" \
5060 "mvc 160(8,15), 48(1)\n\t" \
5061 "mvc 168(8,15), 56(1)\n\t" \
5062 "mvc 176(8,15), 64(1)\n\t" \
5063 "mvc 184(8,15), 72(1)\n\t" \
5064 "lg 1, 0(1)\n\t" \
5065 VALGRIND_CALL_NOREDIR_R1 \
5066 "lgr %0, 2\n\t" \
5067 "aghi 15,192\n\t" \
5068 VALGRIND_CFI_EPILOGUE \
5069 : /*out*/ "=d" (_res) \
5070 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
5071 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5072 ); \
5073 lval = (__typeof__(lval)) _res; \
5074 } while (0)
5075
5076#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
5077 arg6, arg7 ,arg8, arg9, arg10) \
5078 do { \
5079 volatile OrigFn _orig = (orig); \
5080 volatile unsigned long _argvec[11]; \
5081 volatile unsigned long _res; \
5082 _argvec[0] = (unsigned long)_orig.nraddr; \
5083 _argvec[1] = (unsigned long)arg1; \
5084 _argvec[2] = (unsigned long)arg2; \
5085 _argvec[3] = (unsigned long)arg3; \
5086 _argvec[4] = (unsigned long)arg4; \
5087 _argvec[5] = (unsigned long)arg5; \
5088 _argvec[6] = (unsigned long)arg6; \
5089 _argvec[7] = (unsigned long)arg7; \
5090 _argvec[8] = (unsigned long)arg8; \
5091 _argvec[9] = (unsigned long)arg9; \
5092 _argvec[10] = (unsigned long)arg10; \
5093 __asm__ volatile( \
5094 VALGRIND_CFI_PROLOGUE \
5095 "aghi 15,-200\n\t" \
5096 "lg 2, 8(1)\n\t" \
5097 "lg 3,16(1)\n\t" \
5098 "lg 4,24(1)\n\t" \
5099 "lg 5,32(1)\n\t" \
5100 "lg 6,40(1)\n\t" \
5101 "mvc 160(8,15), 48(1)\n\t" \
5102 "mvc 168(8,15), 56(1)\n\t" \
5103 "mvc 176(8,15), 64(1)\n\t" \
5104 "mvc 184(8,15), 72(1)\n\t" \
5105 "mvc 192(8,15), 80(1)\n\t" \
5106 "lg 1, 0(1)\n\t" \
5107 VALGRIND_CALL_NOREDIR_R1 \
5108 "lgr %0, 2\n\t" \
5109 "aghi 15,200\n\t" \
5110 VALGRIND_CFI_EPILOGUE \
5111 : /*out*/ "=d" (_res) \
5112 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
5113 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5114 ); \
5115 lval = (__typeof__(lval)) _res; \
5116 } while (0)
5117
5118#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
5119 arg6, arg7 ,arg8, arg9, arg10, arg11) \
5120 do { \
5121 volatile OrigFn _orig = (orig); \
5122 volatile unsigned long _argvec[12]; \
5123 volatile unsigned long _res; \
5124 _argvec[0] = (unsigned long)_orig.nraddr; \
5125 _argvec[1] = (unsigned long)arg1; \
5126 _argvec[2] = (unsigned long)arg2; \
5127 _argvec[3] = (unsigned long)arg3; \
5128 _argvec[4] = (unsigned long)arg4; \
5129 _argvec[5] = (unsigned long)arg5; \
5130 _argvec[6] = (unsigned long)arg6; \
5131 _argvec[7] = (unsigned long)arg7; \
5132 _argvec[8] = (unsigned long)arg8; \
5133 _argvec[9] = (unsigned long)arg9; \
5134 _argvec[10] = (unsigned long)arg10; \
5135 _argvec[11] = (unsigned long)arg11; \
5136 __asm__ volatile( \
5137 VALGRIND_CFI_PROLOGUE \
5138 "aghi 15,-208\n\t" \
5139 "lg 2, 8(1)\n\t" \
5140 "lg 3,16(1)\n\t" \
5141 "lg 4,24(1)\n\t" \
5142 "lg 5,32(1)\n\t" \
5143 "lg 6,40(1)\n\t" \
5144 "mvc 160(8,15), 48(1)\n\t" \
5145 "mvc 168(8,15), 56(1)\n\t" \
5146 "mvc 176(8,15), 64(1)\n\t" \
5147 "mvc 184(8,15), 72(1)\n\t" \
5148 "mvc 192(8,15), 80(1)\n\t" \
5149 "mvc 200(8,15), 88(1)\n\t" \
5150 "lg 1, 0(1)\n\t" \
5151 VALGRIND_CALL_NOREDIR_R1 \
5152 "lgr %0, 2\n\t" \
5153 "aghi 15,208\n\t" \
5154 VALGRIND_CFI_EPILOGUE \
5155 : /*out*/ "=d" (_res) \
5156 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
5157 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5158 ); \
5159 lval = (__typeof__(lval)) _res; \
5160 } while (0)
5161
5162#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
5163 arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\
5164 do { \
5165 volatile OrigFn _orig = (orig); \
5166 volatile unsigned long _argvec[13]; \
5167 volatile unsigned long _res; \
5168 _argvec[0] = (unsigned long)_orig.nraddr; \
5169 _argvec[1] = (unsigned long)arg1; \
5170 _argvec[2] = (unsigned long)arg2; \
5171 _argvec[3] = (unsigned long)arg3; \
5172 _argvec[4] = (unsigned long)arg4; \
5173 _argvec[5] = (unsigned long)arg5; \
5174 _argvec[6] = (unsigned long)arg6; \
5175 _argvec[7] = (unsigned long)arg7; \
5176 _argvec[8] = (unsigned long)arg8; \
5177 _argvec[9] = (unsigned long)arg9; \
5178 _argvec[10] = (unsigned long)arg10; \
5179 _argvec[11] = (unsigned long)arg11; \
5180 _argvec[12] = (unsigned long)arg12; \
5181 __asm__ volatile( \
5182 VALGRIND_CFI_PROLOGUE \
5183 "aghi 15,-216\n\t" \
5184 "lg 2, 8(1)\n\t" \
5185 "lg 3,16(1)\n\t" \
5186 "lg 4,24(1)\n\t" \
5187 "lg 5,32(1)\n\t" \
5188 "lg 6,40(1)\n\t" \
5189 "mvc 160(8,15), 48(1)\n\t" \
5190 "mvc 168(8,15), 56(1)\n\t" \
5191 "mvc 176(8,15), 64(1)\n\t" \
5192 "mvc 184(8,15), 72(1)\n\t" \
5193 "mvc 192(8,15), 80(1)\n\t" \
5194 "mvc 200(8,15), 88(1)\n\t" \
5195 "mvc 208(8,15), 96(1)\n\t" \
5196 "lg 1, 0(1)\n\t" \
5197 VALGRIND_CALL_NOREDIR_R1 \
5198 "lgr %0, 2\n\t" \
5199 "aghi 15,216\n\t" \
5200 VALGRIND_CFI_EPILOGUE \
5201 : /*out*/ "=d" (_res) \
5202 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
5203 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5204 ); \
5205 lval = (__typeof__(lval)) _res; \
5206 } while (0)
5207
5208
5209#endif /* PLAT_s390x_linux */
5210
petarj4df0bfc2013-02-27 23:17:33 +00005211/* ------------------------- mips32-linux ----------------------- */
sewardj5db15402012-06-07 09:13:21 +00005212
5213#if defined(PLAT_mips32_linux)
5214
5215/* These regs are trashed by the hidden call. */
5216#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \
5217"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
5218"$25", "$31"
5219
5220/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
5221 long) == 4. */
5222
5223#define CALL_FN_W_v(lval, orig) \
5224 do { \
5225 volatile OrigFn _orig = (orig); \
5226 volatile unsigned long _argvec[1]; \
5227 volatile unsigned long _res; \
5228 _argvec[0] = (unsigned long)_orig.nraddr; \
5229 __asm__ volatile( \
5230 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005231 "sw $28, 0($29) \n\t" \
5232 "sw $31, 4($29) \n\t" \
5233 "subu $29, $29, 16 \n\t" \
5234 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005235 VALGRIND_CALL_NOREDIR_T9 \
5236 "addu $29, $29, 16\n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005237 "lw $28, 0($29) \n\t" \
5238 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005239 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005240 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005241 : /*out*/ "=r" (_res) \
5242 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005243 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005244 ); \
5245 lval = (__typeof__(lval)) _res; \
5246 } while (0)
5247
5248#define CALL_FN_W_W(lval, orig, arg1) \
5249 do { \
5250 volatile OrigFn _orig = (orig); \
5251 volatile unsigned long _argvec[2]; \
5252 volatile unsigned long _res; \
5253 _argvec[0] = (unsigned long)_orig.nraddr; \
5254 _argvec[1] = (unsigned long)(arg1); \
5255 __asm__ volatile( \
5256 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005257 "sw $28, 0($29) \n\t" \
5258 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005259 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005260 "lw $4, 4(%1) \n\t" /* arg1*/ \
5261 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005262 VALGRIND_CALL_NOREDIR_T9 \
5263 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005264 "lw $28, 0($29) \n\t" \
5265 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005266 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005267 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005268 : /*out*/ "=r" (_res) \
petarj4df0bfc2013-02-27 23:17:33 +00005269 : /*in*/ "0" (&_argvec[0]) \
5270 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005271 ); \
5272 lval = (__typeof__(lval)) _res; \
5273 } while (0)
5274
5275#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
5276 do { \
5277 volatile OrigFn _orig = (orig); \
5278 volatile unsigned long _argvec[3]; \
5279 volatile unsigned long _res; \
5280 _argvec[0] = (unsigned long)_orig.nraddr; \
5281 _argvec[1] = (unsigned long)(arg1); \
5282 _argvec[2] = (unsigned long)(arg2); \
5283 __asm__ volatile( \
5284 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005285 "sw $28, 0($29) \n\t" \
5286 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005287 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005288 "lw $4, 4(%1) \n\t" \
5289 "lw $5, 8(%1) \n\t" \
5290 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005291 VALGRIND_CALL_NOREDIR_T9 \
5292 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005293 "lw $28, 0($29) \n\t" \
5294 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005295 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005296 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005297 : /*out*/ "=r" (_res) \
5298 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005299 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005300 ); \
5301 lval = (__typeof__(lval)) _res; \
5302 } while (0)
5303
5304#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
5305 do { \
5306 volatile OrigFn _orig = (orig); \
5307 volatile unsigned long _argvec[4]; \
5308 volatile unsigned long _res; \
5309 _argvec[0] = (unsigned long)_orig.nraddr; \
5310 _argvec[1] = (unsigned long)(arg1); \
5311 _argvec[2] = (unsigned long)(arg2); \
5312 _argvec[3] = (unsigned long)(arg3); \
5313 __asm__ volatile( \
5314 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005315 "sw $28, 0($29) \n\t" \
5316 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005317 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005318 "lw $4, 4(%1) \n\t" \
5319 "lw $5, 8(%1) \n\t" \
5320 "lw $6, 12(%1) \n\t" \
5321 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005322 VALGRIND_CALL_NOREDIR_T9 \
5323 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005324 "lw $28, 0($29) \n\t" \
5325 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005326 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005327 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005328 : /*out*/ "=r" (_res) \
5329 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005330 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005331 ); \
5332 lval = (__typeof__(lval)) _res; \
5333 } while (0)
5334
5335#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
5336 do { \
5337 volatile OrigFn _orig = (orig); \
5338 volatile unsigned long _argvec[5]; \
5339 volatile unsigned long _res; \
5340 _argvec[0] = (unsigned long)_orig.nraddr; \
5341 _argvec[1] = (unsigned long)(arg1); \
5342 _argvec[2] = (unsigned long)(arg2); \
5343 _argvec[3] = (unsigned long)(arg3); \
5344 _argvec[4] = (unsigned long)(arg4); \
5345 __asm__ volatile( \
5346 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005347 "sw $28, 0($29) \n\t" \
5348 "sw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005349 "subu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005350 "lw $4, 4(%1) \n\t" \
5351 "lw $5, 8(%1) \n\t" \
5352 "lw $6, 12(%1) \n\t" \
5353 "lw $7, 16(%1) \n\t" \
5354 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005355 VALGRIND_CALL_NOREDIR_T9 \
5356 "addu $29, $29, 16 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005357 "lw $28, 0($29) \n\t" \
5358 "lw $31, 4($29) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005359 "addu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005360 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005361 : /*out*/ "=r" (_res) \
5362 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005363 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005364 ); \
5365 lval = (__typeof__(lval)) _res; \
5366 } while (0)
5367
5368#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
5369 do { \
5370 volatile OrigFn _orig = (orig); \
5371 volatile unsigned long _argvec[6]; \
5372 volatile unsigned long _res; \
5373 _argvec[0] = (unsigned long)_orig.nraddr; \
5374 _argvec[1] = (unsigned long)(arg1); \
5375 _argvec[2] = (unsigned long)(arg2); \
5376 _argvec[3] = (unsigned long)(arg3); \
5377 _argvec[4] = (unsigned long)(arg4); \
5378 _argvec[5] = (unsigned long)(arg5); \
5379 __asm__ volatile( \
5380 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005381 "sw $28, 0($29) \n\t" \
5382 "sw $31, 4($29) \n\t" \
5383 "lw $4, 20(%1) \n\t" \
5384 "subu $29, $29, 24\n\t" \
5385 "sw $4, 16($29) \n\t" \
5386 "lw $4, 4(%1) \n\t" \
5387 "lw $5, 8(%1) \n\t" \
5388 "lw $6, 12(%1) \n\t" \
5389 "lw $7, 16(%1) \n\t" \
5390 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005391 VALGRIND_CALL_NOREDIR_T9 \
5392 "addu $29, $29, 24 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005393 "lw $28, 0($29) \n\t" \
5394 "lw $31, 4($29) \n\t" \
5395 "addu $29, $29, 8 \n\t" \
5396 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005397 : /*out*/ "=r" (_res) \
5398 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005399 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005400 ); \
5401 lval = (__typeof__(lval)) _res; \
5402 } while (0)
5403#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
5404 do { \
5405 volatile OrigFn _orig = (orig); \
5406 volatile unsigned long _argvec[7]; \
5407 volatile unsigned long _res; \
5408 _argvec[0] = (unsigned long)_orig.nraddr; \
5409 _argvec[1] = (unsigned long)(arg1); \
5410 _argvec[2] = (unsigned long)(arg2); \
5411 _argvec[3] = (unsigned long)(arg3); \
5412 _argvec[4] = (unsigned long)(arg4); \
5413 _argvec[5] = (unsigned long)(arg5); \
5414 _argvec[6] = (unsigned long)(arg6); \
5415 __asm__ volatile( \
5416 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005417 "sw $28, 0($29) \n\t" \
5418 "sw $31, 4($29) \n\t" \
5419 "lw $4, 20(%1) \n\t" \
5420 "subu $29, $29, 32\n\t" \
5421 "sw $4, 16($29) \n\t" \
5422 "lw $4, 24(%1) \n\t" \
sewardj5db15402012-06-07 09:13:21 +00005423 "nop\n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005424 "sw $4, 20($29) \n\t" \
5425 "lw $4, 4(%1) \n\t" \
5426 "lw $5, 8(%1) \n\t" \
5427 "lw $6, 12(%1) \n\t" \
5428 "lw $7, 16(%1) \n\t" \
5429 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005430 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00005431 "addu $29, $29, 32 \n\t" \
5432 "lw $28, 0($29) \n\t" \
5433 "lw $31, 4($29) \n\t" \
5434 "addu $29, $29, 8 \n\t" \
5435 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005436 : /*out*/ "=r" (_res) \
5437 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005438 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005439 ); \
5440 lval = (__typeof__(lval)) _res; \
5441 } while (0)
5442
5443#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5444 arg7) \
5445 do { \
5446 volatile OrigFn _orig = (orig); \
5447 volatile unsigned long _argvec[8]; \
5448 volatile unsigned long _res; \
5449 _argvec[0] = (unsigned long)_orig.nraddr; \
5450 _argvec[1] = (unsigned long)(arg1); \
5451 _argvec[2] = (unsigned long)(arg2); \
5452 _argvec[3] = (unsigned long)(arg3); \
5453 _argvec[4] = (unsigned long)(arg4); \
5454 _argvec[5] = (unsigned long)(arg5); \
5455 _argvec[6] = (unsigned long)(arg6); \
5456 _argvec[7] = (unsigned long)(arg7); \
5457 __asm__ volatile( \
5458 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005459 "sw $28, 0($29) \n\t" \
5460 "sw $31, 4($29) \n\t" \
5461 "lw $4, 20(%1) \n\t" \
5462 "subu $29, $29, 32\n\t" \
5463 "sw $4, 16($29) \n\t" \
5464 "lw $4, 24(%1) \n\t" \
5465 "sw $4, 20($29) \n\t" \
5466 "lw $4, 28(%1) \n\t" \
5467 "sw $4, 24($29) \n\t" \
5468 "lw $4, 4(%1) \n\t" \
5469 "lw $5, 8(%1) \n\t" \
5470 "lw $6, 12(%1) \n\t" \
5471 "lw $7, 16(%1) \n\t" \
5472 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005473 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00005474 "addu $29, $29, 32 \n\t" \
5475 "lw $28, 0($29) \n\t" \
5476 "lw $31, 4($29) \n\t" \
5477 "addu $29, $29, 8 \n\t" \
5478 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005479 : /*out*/ "=r" (_res) \
5480 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005481 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005482 ); \
5483 lval = (__typeof__(lval)) _res; \
5484 } while (0)
5485
5486#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5487 arg7,arg8) \
5488 do { \
5489 volatile OrigFn _orig = (orig); \
5490 volatile unsigned long _argvec[9]; \
5491 volatile unsigned long _res; \
5492 _argvec[0] = (unsigned long)_orig.nraddr; \
5493 _argvec[1] = (unsigned long)(arg1); \
5494 _argvec[2] = (unsigned long)(arg2); \
5495 _argvec[3] = (unsigned long)(arg3); \
5496 _argvec[4] = (unsigned long)(arg4); \
5497 _argvec[5] = (unsigned long)(arg5); \
5498 _argvec[6] = (unsigned long)(arg6); \
5499 _argvec[7] = (unsigned long)(arg7); \
5500 _argvec[8] = (unsigned long)(arg8); \
5501 __asm__ volatile( \
5502 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005503 "sw $28, 0($29) \n\t" \
5504 "sw $31, 4($29) \n\t" \
5505 "lw $4, 20(%1) \n\t" \
5506 "subu $29, $29, 40\n\t" \
5507 "sw $4, 16($29) \n\t" \
5508 "lw $4, 24(%1) \n\t" \
5509 "sw $4, 20($29) \n\t" \
5510 "lw $4, 28(%1) \n\t" \
5511 "sw $4, 24($29) \n\t" \
5512 "lw $4, 32(%1) \n\t" \
5513 "sw $4, 28($29) \n\t" \
5514 "lw $4, 4(%1) \n\t" \
5515 "lw $5, 8(%1) \n\t" \
5516 "lw $6, 12(%1) \n\t" \
5517 "lw $7, 16(%1) \n\t" \
5518 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005519 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00005520 "addu $29, $29, 40 \n\t" \
5521 "lw $28, 0($29) \n\t" \
5522 "lw $31, 4($29) \n\t" \
5523 "addu $29, $29, 8 \n\t" \
5524 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005525 : /*out*/ "=r" (_res) \
5526 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005527 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005528 ); \
5529 lval = (__typeof__(lval)) _res; \
5530 } while (0)
5531
5532#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5533 arg7,arg8,arg9) \
5534 do { \
5535 volatile OrigFn _orig = (orig); \
5536 volatile unsigned long _argvec[10]; \
5537 volatile unsigned long _res; \
5538 _argvec[0] = (unsigned long)_orig.nraddr; \
5539 _argvec[1] = (unsigned long)(arg1); \
5540 _argvec[2] = (unsigned long)(arg2); \
5541 _argvec[3] = (unsigned long)(arg3); \
5542 _argvec[4] = (unsigned long)(arg4); \
5543 _argvec[5] = (unsigned long)(arg5); \
5544 _argvec[6] = (unsigned long)(arg6); \
5545 _argvec[7] = (unsigned long)(arg7); \
5546 _argvec[8] = (unsigned long)(arg8); \
5547 _argvec[9] = (unsigned long)(arg9); \
5548 __asm__ volatile( \
5549 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005550 "sw $28, 0($29) \n\t" \
5551 "sw $31, 4($29) \n\t" \
5552 "lw $4, 20(%1) \n\t" \
5553 "subu $29, $29, 40\n\t" \
5554 "sw $4, 16($29) \n\t" \
5555 "lw $4, 24(%1) \n\t" \
5556 "sw $4, 20($29) \n\t" \
5557 "lw $4, 28(%1) \n\t" \
5558 "sw $4, 24($29) \n\t" \
5559 "lw $4, 32(%1) \n\t" \
5560 "sw $4, 28($29) \n\t" \
5561 "lw $4, 36(%1) \n\t" \
5562 "sw $4, 32($29) \n\t" \
5563 "lw $4, 4(%1) \n\t" \
5564 "lw $5, 8(%1) \n\t" \
5565 "lw $6, 12(%1) \n\t" \
5566 "lw $7, 16(%1) \n\t" \
5567 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005568 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00005569 "addu $29, $29, 40 \n\t" \
5570 "lw $28, 0($29) \n\t" \
5571 "lw $31, 4($29) \n\t" \
5572 "addu $29, $29, 8 \n\t" \
5573 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005574 : /*out*/ "=r" (_res) \
5575 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005576 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005577 ); \
5578 lval = (__typeof__(lval)) _res; \
5579 } while (0)
5580
5581#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5582 arg7,arg8,arg9,arg10) \
5583 do { \
5584 volatile OrigFn _orig = (orig); \
5585 volatile unsigned long _argvec[11]; \
5586 volatile unsigned long _res; \
5587 _argvec[0] = (unsigned long)_orig.nraddr; \
5588 _argvec[1] = (unsigned long)(arg1); \
5589 _argvec[2] = (unsigned long)(arg2); \
5590 _argvec[3] = (unsigned long)(arg3); \
5591 _argvec[4] = (unsigned long)(arg4); \
5592 _argvec[5] = (unsigned long)(arg5); \
5593 _argvec[6] = (unsigned long)(arg6); \
5594 _argvec[7] = (unsigned long)(arg7); \
5595 _argvec[8] = (unsigned long)(arg8); \
5596 _argvec[9] = (unsigned long)(arg9); \
5597 _argvec[10] = (unsigned long)(arg10); \
5598 __asm__ volatile( \
5599 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005600 "sw $28, 0($29) \n\t" \
5601 "sw $31, 4($29) \n\t" \
5602 "lw $4, 20(%1) \n\t" \
5603 "subu $29, $29, 48\n\t" \
5604 "sw $4, 16($29) \n\t" \
5605 "lw $4, 24(%1) \n\t" \
5606 "sw $4, 20($29) \n\t" \
5607 "lw $4, 28(%1) \n\t" \
5608 "sw $4, 24($29) \n\t" \
5609 "lw $4, 32(%1) \n\t" \
5610 "sw $4, 28($29) \n\t" \
5611 "lw $4, 36(%1) \n\t" \
5612 "sw $4, 32($29) \n\t" \
5613 "lw $4, 40(%1) \n\t" \
5614 "sw $4, 36($29) \n\t" \
5615 "lw $4, 4(%1) \n\t" \
5616 "lw $5, 8(%1) \n\t" \
5617 "lw $6, 12(%1) \n\t" \
5618 "lw $7, 16(%1) \n\t" \
5619 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005620 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00005621 "addu $29, $29, 48 \n\t" \
5622 "lw $28, 0($29) \n\t" \
5623 "lw $31, 4($29) \n\t" \
5624 "addu $29, $29, 8 \n\t" \
5625 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005626 : /*out*/ "=r" (_res) \
5627 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005628 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005629 ); \
5630 lval = (__typeof__(lval)) _res; \
5631 } while (0)
5632
5633#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
5634 arg6,arg7,arg8,arg9,arg10, \
5635 arg11) \
5636 do { \
5637 volatile OrigFn _orig = (orig); \
5638 volatile unsigned long _argvec[12]; \
5639 volatile unsigned long _res; \
5640 _argvec[0] = (unsigned long)_orig.nraddr; \
5641 _argvec[1] = (unsigned long)(arg1); \
5642 _argvec[2] = (unsigned long)(arg2); \
5643 _argvec[3] = (unsigned long)(arg3); \
5644 _argvec[4] = (unsigned long)(arg4); \
5645 _argvec[5] = (unsigned long)(arg5); \
5646 _argvec[6] = (unsigned long)(arg6); \
5647 _argvec[7] = (unsigned long)(arg7); \
5648 _argvec[8] = (unsigned long)(arg8); \
5649 _argvec[9] = (unsigned long)(arg9); \
5650 _argvec[10] = (unsigned long)(arg10); \
5651 _argvec[11] = (unsigned long)(arg11); \
5652 __asm__ volatile( \
5653 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005654 "sw $28, 0($29) \n\t" \
5655 "sw $31, 4($29) \n\t" \
5656 "lw $4, 20(%1) \n\t" \
5657 "subu $29, $29, 48\n\t" \
5658 "sw $4, 16($29) \n\t" \
5659 "lw $4, 24(%1) \n\t" \
5660 "sw $4, 20($29) \n\t" \
5661 "lw $4, 28(%1) \n\t" \
5662 "sw $4, 24($29) \n\t" \
5663 "lw $4, 32(%1) \n\t" \
5664 "sw $4, 28($29) \n\t" \
5665 "lw $4, 36(%1) \n\t" \
5666 "sw $4, 32($29) \n\t" \
5667 "lw $4, 40(%1) \n\t" \
5668 "sw $4, 36($29) \n\t" \
5669 "lw $4, 44(%1) \n\t" \
5670 "sw $4, 40($29) \n\t" \
5671 "lw $4, 4(%1) \n\t" \
5672 "lw $5, 8(%1) \n\t" \
5673 "lw $6, 12(%1) \n\t" \
5674 "lw $7, 16(%1) \n\t" \
5675 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005676 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00005677 "addu $29, $29, 48 \n\t" \
5678 "lw $28, 0($29) \n\t" \
5679 "lw $31, 4($29) \n\t" \
5680 "addu $29, $29, 8 \n\t" \
5681 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005682 : /*out*/ "=r" (_res) \
5683 : /*in*/ "0" (&_argvec[0]) \
petarj4df0bfc2013-02-27 23:17:33 +00005684 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005685 ); \
5686 lval = (__typeof__(lval)) _res; \
5687 } while (0)
5688
5689#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
5690 arg6,arg7,arg8,arg9,arg10, \
5691 arg11,arg12) \
5692 do { \
5693 volatile OrigFn _orig = (orig); \
5694 volatile unsigned long _argvec[13]; \
5695 volatile unsigned long _res; \
5696 _argvec[0] = (unsigned long)_orig.nraddr; \
5697 _argvec[1] = (unsigned long)(arg1); \
5698 _argvec[2] = (unsigned long)(arg2); \
5699 _argvec[3] = (unsigned long)(arg3); \
5700 _argvec[4] = (unsigned long)(arg4); \
5701 _argvec[5] = (unsigned long)(arg5); \
5702 _argvec[6] = (unsigned long)(arg6); \
5703 _argvec[7] = (unsigned long)(arg7); \
5704 _argvec[8] = (unsigned long)(arg8); \
5705 _argvec[9] = (unsigned long)(arg9); \
5706 _argvec[10] = (unsigned long)(arg10); \
5707 _argvec[11] = (unsigned long)(arg11); \
5708 _argvec[12] = (unsigned long)(arg12); \
5709 __asm__ volatile( \
5710 "subu $29, $29, 8 \n\t" \
petarj4df0bfc2013-02-27 23:17:33 +00005711 "sw $28, 0($29) \n\t" \
5712 "sw $31, 4($29) \n\t" \
5713 "lw $4, 20(%1) \n\t" \
5714 "subu $29, $29, 56\n\t" \
5715 "sw $4, 16($29) \n\t" \
5716 "lw $4, 24(%1) \n\t" \
5717 "sw $4, 20($29) \n\t" \
5718 "lw $4, 28(%1) \n\t" \
5719 "sw $4, 24($29) \n\t" \
5720 "lw $4, 32(%1) \n\t" \
5721 "sw $4, 28($29) \n\t" \
5722 "lw $4, 36(%1) \n\t" \
5723 "sw $4, 32($29) \n\t" \
5724 "lw $4, 40(%1) \n\t" \
5725 "sw $4, 36($29) \n\t" \
5726 "lw $4, 44(%1) \n\t" \
5727 "sw $4, 40($29) \n\t" \
5728 "lw $4, 48(%1) \n\t" \
5729 "sw $4, 44($29) \n\t" \
5730 "lw $4, 4(%1) \n\t" \
5731 "lw $5, 8(%1) \n\t" \
5732 "lw $6, 12(%1) \n\t" \
5733 "lw $7, 16(%1) \n\t" \
5734 "lw $25, 0(%1) \n\t" /* target->t9 */ \
sewardj5db15402012-06-07 09:13:21 +00005735 VALGRIND_CALL_NOREDIR_T9 \
petarj4df0bfc2013-02-27 23:17:33 +00005736 "addu $29, $29, 56 \n\t" \
5737 "lw $28, 0($29) \n\t" \
5738 "lw $31, 4($29) \n\t" \
5739 "addu $29, $29, 8 \n\t" \
5740 "move %0, $2\n" \
sewardj5db15402012-06-07 09:13:21 +00005741 : /*out*/ "=r" (_res) \
petarj4df0bfc2013-02-27 23:17:33 +00005742 : /*in*/ "r" (&_argvec[0]) \
5743 : /*trash*/ "memory", __CALLER_SAVED_REGS \
sewardj5db15402012-06-07 09:13:21 +00005744 ); \
5745 lval = (__typeof__(lval)) _res; \
5746 } while (0)
5747
5748#endif /* PLAT_mips32_linux */
5749
petarj4df0bfc2013-02-27 23:17:33 +00005750/* ------------------------- mips64-linux ------------------------- */
5751
5752#if defined(PLAT_mips64_linux)
5753
5754/* These regs are trashed by the hidden call. */
5755#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \
5756"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
5757"$25", "$31"
5758
5759/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
5760 long) == 4. */
5761
5762#define CALL_FN_W_v(lval, orig) \
5763 do { \
5764 volatile OrigFn _orig = (orig); \
5765 volatile unsigned long _argvec[1]; \
5766 volatile unsigned long _res; \
5767 _argvec[0] = (unsigned long)_orig.nraddr; \
5768 __asm__ volatile( \
5769 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5770 VALGRIND_CALL_NOREDIR_T9 \
5771 "move %0, $2\n" \
5772 : /*out*/ "=r" (_res) \
5773 : /*in*/ "0" (&_argvec[0]) \
5774 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5775 ); \
5776 lval = (__typeof__(lval)) _res; \
5777 } while (0)
5778
5779#define CALL_FN_W_W(lval, orig, arg1) \
5780 do { \
5781 volatile OrigFn _orig = (orig); \
5782 volatile unsigned long _argvec[2]; \
5783 volatile unsigned long _res; \
5784 _argvec[0] = (unsigned long)_orig.nraddr; \
5785 _argvec[1] = (unsigned long)(arg1); \
5786 __asm__ volatile( \
5787 "ld $4, 8(%1)\n\t" /* arg1*/ \
5788 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5789 VALGRIND_CALL_NOREDIR_T9 \
5790 "move %0, $2\n" \
5791 : /*out*/ "=r" (_res) \
5792 : /*in*/ "r" (&_argvec[0]) \
5793 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5794 ); \
5795 lval = (__typeof__(lval)) _res; \
5796 } while (0)
5797
5798#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
5799 do { \
5800 volatile OrigFn _orig = (orig); \
5801 volatile unsigned long _argvec[3]; \
5802 volatile unsigned long _res; \
5803 _argvec[0] = (unsigned long)_orig.nraddr; \
5804 _argvec[1] = (unsigned long)(arg1); \
5805 _argvec[2] = (unsigned long)(arg2); \
5806 __asm__ volatile( \
5807 "ld $4, 8(%1)\n\t" \
5808 "ld $5, 16(%1)\n\t" \
5809 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5810 VALGRIND_CALL_NOREDIR_T9 \
5811 "move %0, $2\n" \
5812 : /*out*/ "=r" (_res) \
5813 : /*in*/ "r" (&_argvec[0]) \
5814 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5815 ); \
5816 lval = (__typeof__(lval)) _res; \
5817 } while (0)
5818
5819#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
5820 do { \
5821 volatile OrigFn _orig = (orig); \
5822 volatile unsigned long _argvec[4]; \
5823 volatile unsigned long _res; \
5824 _argvec[0] = (unsigned long)_orig.nraddr; \
5825 _argvec[1] = (unsigned long)(arg1); \
5826 _argvec[2] = (unsigned long)(arg2); \
5827 _argvec[3] = (unsigned long)(arg3); \
5828 __asm__ volatile( \
5829 "ld $4, 8(%1)\n\t" \
5830 "ld $5, 16(%1)\n\t" \
5831 "ld $6, 24(%1)\n\t" \
5832 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5833 VALGRIND_CALL_NOREDIR_T9 \
5834 "move %0, $2\n" \
5835 : /*out*/ "=r" (_res) \
5836 : /*in*/ "r" (&_argvec[0]) \
5837 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5838 ); \
5839 lval = (__typeof__(lval)) _res; \
5840 } while (0)
5841
5842#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
5843 do { \
5844 volatile OrigFn _orig = (orig); \
5845 volatile unsigned long _argvec[5]; \
5846 volatile unsigned long _res; \
5847 _argvec[0] = (unsigned long)_orig.nraddr; \
5848 _argvec[1] = (unsigned long)(arg1); \
5849 _argvec[2] = (unsigned long)(arg2); \
5850 _argvec[3] = (unsigned long)(arg3); \
5851 _argvec[4] = (unsigned long)(arg4); \
5852 __asm__ volatile( \
5853 "ld $4, 8(%1)\n\t" \
5854 "ld $5, 16(%1)\n\t" \
5855 "ld $6, 24(%1)\n\t" \
5856 "ld $7, 32(%1)\n\t" \
5857 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5858 VALGRIND_CALL_NOREDIR_T9 \
5859 "move %0, $2\n" \
5860 : /*out*/ "=r" (_res) \
5861 : /*in*/ "r" (&_argvec[0]) \
5862 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5863 ); \
5864 lval = (__typeof__(lval)) _res; \
5865 } while (0)
5866
5867#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
5868 do { \
5869 volatile OrigFn _orig = (orig); \
5870 volatile unsigned long _argvec[6]; \
5871 volatile unsigned long _res; \
5872 _argvec[0] = (unsigned long)_orig.nraddr; \
5873 _argvec[1] = (unsigned long)(arg1); \
5874 _argvec[2] = (unsigned long)(arg2); \
5875 _argvec[3] = (unsigned long)(arg3); \
5876 _argvec[4] = (unsigned long)(arg4); \
5877 _argvec[5] = (unsigned long)(arg5); \
5878 __asm__ volatile( \
5879 "ld $4, 8(%1)\n\t" \
5880 "ld $5, 16(%1)\n\t" \
5881 "ld $6, 24(%1)\n\t" \
5882 "ld $7, 32(%1)\n\t" \
5883 "ld $8, 40(%1)\n\t" \
5884 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5885 VALGRIND_CALL_NOREDIR_T9 \
5886 "move %0, $2\n" \
5887 : /*out*/ "=r" (_res) \
5888 : /*in*/ "r" (&_argvec[0]) \
5889 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5890 ); \
5891 lval = (__typeof__(lval)) _res; \
5892 } while (0)
5893
5894#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
5895 do { \
5896 volatile OrigFn _orig = (orig); \
5897 volatile unsigned long _argvec[7]; \
5898 volatile unsigned long _res; \
5899 _argvec[0] = (unsigned long)_orig.nraddr; \
5900 _argvec[1] = (unsigned long)(arg1); \
5901 _argvec[2] = (unsigned long)(arg2); \
5902 _argvec[3] = (unsigned long)(arg3); \
5903 _argvec[4] = (unsigned long)(arg4); \
5904 _argvec[5] = (unsigned long)(arg5); \
5905 _argvec[6] = (unsigned long)(arg6); \
5906 __asm__ volatile( \
5907 "ld $4, 8(%1)\n\t" \
5908 "ld $5, 16(%1)\n\t" \
5909 "ld $6, 24(%1)\n\t" \
5910 "ld $7, 32(%1)\n\t" \
5911 "ld $8, 40(%1)\n\t" \
5912 "ld $9, 48(%1)\n\t" \
5913 "ld $25, 0(%1)\n\t" /* target->t9 */ \
5914 VALGRIND_CALL_NOREDIR_T9 \
5915 "move %0, $2\n" \
5916 : /*out*/ "=r" (_res) \
5917 : /*in*/ "r" (&_argvec[0]) \
5918 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5919 ); \
5920 lval = (__typeof__(lval)) _res; \
5921 } while (0)
5922
5923#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5924 arg7) \
5925 do { \
5926 volatile OrigFn _orig = (orig); \
5927 volatile unsigned long _argvec[8]; \
5928 volatile unsigned long _res; \
5929 _argvec[0] = (unsigned long)_orig.nraddr; \
5930 _argvec[1] = (unsigned long)(arg1); \
5931 _argvec[2] = (unsigned long)(arg2); \
5932 _argvec[3] = (unsigned long)(arg3); \
5933 _argvec[4] = (unsigned long)(arg4); \
5934 _argvec[5] = (unsigned long)(arg5); \
5935 _argvec[6] = (unsigned long)(arg6); \
5936 _argvec[7] = (unsigned long)(arg7); \
5937 __asm__ volatile( \
5938 "ld $4, 8(%1)\n\t" \
5939 "ld $5, 16(%1)\n\t" \
5940 "ld $6, 24(%1)\n\t" \
5941 "ld $7, 32(%1)\n\t" \
5942 "ld $8, 40(%1)\n\t" \
5943 "ld $9, 48(%1)\n\t" \
5944 "ld $10, 56(%1)\n\t" \
5945 "ld $25, 0(%1) \n\t" /* target->t9 */ \
5946 VALGRIND_CALL_NOREDIR_T9 \
5947 "move %0, $2\n" \
5948 : /*out*/ "=r" (_res) \
5949 : /*in*/ "r" (&_argvec[0]) \
5950 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5951 ); \
5952 lval = (__typeof__(lval)) _res; \
5953 } while (0)
5954
5955#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5956 arg7,arg8) \
5957 do { \
5958 volatile OrigFn _orig = (orig); \
5959 volatile unsigned long _argvec[9]; \
5960 volatile unsigned long _res; \
5961 _argvec[0] = (unsigned long)_orig.nraddr; \
5962 _argvec[1] = (unsigned long)(arg1); \
5963 _argvec[2] = (unsigned long)(arg2); \
5964 _argvec[3] = (unsigned long)(arg3); \
5965 _argvec[4] = (unsigned long)(arg4); \
5966 _argvec[5] = (unsigned long)(arg5); \
5967 _argvec[6] = (unsigned long)(arg6); \
5968 _argvec[7] = (unsigned long)(arg7); \
5969 _argvec[8] = (unsigned long)(arg8); \
5970 __asm__ volatile( \
5971 "ld $4, 8(%1)\n\t" \
5972 "ld $5, 16(%1)\n\t" \
5973 "ld $6, 24(%1)\n\t" \
5974 "ld $7, 32(%1)\n\t" \
5975 "ld $8, 40(%1)\n\t" \
5976 "ld $9, 48(%1)\n\t" \
5977 "ld $10, 56(%1)\n\t" \
5978 "ld $11, 64(%1)\n\t" \
5979 "ld $25, 0(%1) \n\t" /* target->t9 */ \
5980 VALGRIND_CALL_NOREDIR_T9 \
5981 "move %0, $2\n" \
5982 : /*out*/ "=r" (_res) \
5983 : /*in*/ "r" (&_argvec[0]) \
5984 : /*trash*/ "memory", __CALLER_SAVED_REGS \
5985 ); \
5986 lval = (__typeof__(lval)) _res; \
5987 } while (0)
5988
5989#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
5990 arg7,arg8,arg9) \
5991 do { \
5992 volatile OrigFn _orig = (orig); \
5993 volatile unsigned long _argvec[10]; \
5994 volatile unsigned long _res; \
5995 _argvec[0] = (unsigned long)_orig.nraddr; \
5996 _argvec[1] = (unsigned long)(arg1); \
5997 _argvec[2] = (unsigned long)(arg2); \
5998 _argvec[3] = (unsigned long)(arg3); \
5999 _argvec[4] = (unsigned long)(arg4); \
6000 _argvec[5] = (unsigned long)(arg5); \
6001 _argvec[6] = (unsigned long)(arg6); \
6002 _argvec[7] = (unsigned long)(arg7); \
6003 _argvec[8] = (unsigned long)(arg8); \
6004 _argvec[9] = (unsigned long)(arg9); \
6005 __asm__ volatile( \
6006 "dsubu $29, $29, 8\n\t" \
6007 "ld $4, 72(%1)\n\t" \
6008 "sd $4, 0($29)\n\t" \
6009 "ld $4, 8(%1)\n\t" \
6010 "ld $5, 16(%1)\n\t" \
6011 "ld $6, 24(%1)\n\t" \
6012 "ld $7, 32(%1)\n\t" \
6013 "ld $8, 40(%1)\n\t" \
6014 "ld $9, 48(%1)\n\t" \
6015 "ld $10, 56(%1)\n\t" \
6016 "ld $11, 64(%1)\n\t" \
6017 "ld $25, 0(%1)\n\t" /* target->t9 */ \
6018 VALGRIND_CALL_NOREDIR_T9 \
6019 "daddu $29, $29, 8\n\t" \
6020 "move %0, $2\n" \
6021 : /*out*/ "=r" (_res) \
6022 : /*in*/ "r" (&_argvec[0]) \
6023 : /*trash*/ "memory", __CALLER_SAVED_REGS \
6024 ); \
6025 lval = (__typeof__(lval)) _res; \
6026 } while (0)
6027
6028#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
6029 arg7,arg8,arg9,arg10) \
6030 do { \
6031 volatile OrigFn _orig = (orig); \
6032 volatile unsigned long _argvec[11]; \
6033 volatile unsigned long _res; \
6034 _argvec[0] = (unsigned long)_orig.nraddr; \
6035 _argvec[1] = (unsigned long)(arg1); \
6036 _argvec[2] = (unsigned long)(arg2); \
6037 _argvec[3] = (unsigned long)(arg3); \
6038 _argvec[4] = (unsigned long)(arg4); \
6039 _argvec[5] = (unsigned long)(arg5); \
6040 _argvec[6] = (unsigned long)(arg6); \
6041 _argvec[7] = (unsigned long)(arg7); \
6042 _argvec[8] = (unsigned long)(arg8); \
6043 _argvec[9] = (unsigned long)(arg9); \
6044 _argvec[10] = (unsigned long)(arg10); \
6045 __asm__ volatile( \
6046 "dsubu $29, $29, 16\n\t" \
6047 "ld $4, 72(%1)\n\t" \
6048 "sd $4, 0($29)\n\t" \
6049 "ld $4, 80(%1)\n\t" \
6050 "sd $4, 8($29)\n\t" \
6051 "ld $4, 8(%1)\n\t" \
6052 "ld $5, 16(%1)\n\t" \
6053 "ld $6, 24(%1)\n\t" \
6054 "ld $7, 32(%1)\n\t" \
6055 "ld $8, 40(%1)\n\t" \
6056 "ld $9, 48(%1)\n\t" \
6057 "ld $10, 56(%1)\n\t" \
6058 "ld $11, 64(%1)\n\t" \
6059 "ld $25, 0(%1)\n\t" /* target->t9 */ \
6060 VALGRIND_CALL_NOREDIR_T9 \
6061 "daddu $29, $29, 16\n\t" \
6062 "move %0, $2\n" \
6063 : /*out*/ "=r" (_res) \
6064 : /*in*/ "r" (&_argvec[0]) \
6065 : /*trash*/ "memory", __CALLER_SAVED_REGS \
6066 ); \
6067 lval = (__typeof__(lval)) _res; \
6068 } while (0)
6069
6070#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
6071 arg6,arg7,arg8,arg9,arg10, \
6072 arg11) \
6073 do { \
6074 volatile OrigFn _orig = (orig); \
6075 volatile unsigned long _argvec[12]; \
6076 volatile unsigned long _res; \
6077 _argvec[0] = (unsigned long)_orig.nraddr; \
6078 _argvec[1] = (unsigned long)(arg1); \
6079 _argvec[2] = (unsigned long)(arg2); \
6080 _argvec[3] = (unsigned long)(arg3); \
6081 _argvec[4] = (unsigned long)(arg4); \
6082 _argvec[5] = (unsigned long)(arg5); \
6083 _argvec[6] = (unsigned long)(arg6); \
6084 _argvec[7] = (unsigned long)(arg7); \
6085 _argvec[8] = (unsigned long)(arg8); \
6086 _argvec[9] = (unsigned long)(arg9); \
6087 _argvec[10] = (unsigned long)(arg10); \
6088 _argvec[11] = (unsigned long)(arg11); \
6089 __asm__ volatile( \
6090 "dsubu $29, $29, 24\n\t" \
6091 "ld $4, 72(%1)\n\t" \
6092 "sd $4, 0($29)\n\t" \
6093 "ld $4, 80(%1)\n\t" \
6094 "sd $4, 8($29)\n\t" \
6095 "ld $4, 88(%1)\n\t" \
6096 "sd $4, 16($29)\n\t" \
6097 "ld $4, 8(%1)\n\t" \
6098 "ld $5, 16(%1)\n\t" \
6099 "ld $6, 24(%1)\n\t" \
6100 "ld $7, 32(%1)\n\t" \
6101 "ld $8, 40(%1)\n\t" \
6102 "ld $9, 48(%1)\n\t" \
6103 "ld $10, 56(%1)\n\t" \
6104 "ld $11, 64(%1)\n\t" \
6105 "ld $25, 0(%1)\n\t" /* target->t9 */ \
6106 VALGRIND_CALL_NOREDIR_T9 \
6107 "daddu $29, $29, 24\n\t" \
6108 "move %0, $2\n" \
6109 : /*out*/ "=r" (_res) \
6110 : /*in*/ "r" (&_argvec[0]) \
6111 : /*trash*/ "memory", __CALLER_SAVED_REGS \
6112 ); \
6113 lval = (__typeof__(lval)) _res; \
6114 } while (0)
6115
6116#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
6117 arg6,arg7,arg8,arg9,arg10, \
6118 arg11,arg12) \
6119 do { \
6120 volatile OrigFn _orig = (orig); \
6121 volatile unsigned long _argvec[13]; \
6122 volatile unsigned long _res; \
6123 _argvec[0] = (unsigned long)_orig.nraddr; \
6124 _argvec[1] = (unsigned long)(arg1); \
6125 _argvec[2] = (unsigned long)(arg2); \
6126 _argvec[3] = (unsigned long)(arg3); \
6127 _argvec[4] = (unsigned long)(arg4); \
6128 _argvec[5] = (unsigned long)(arg5); \
6129 _argvec[6] = (unsigned long)(arg6); \
6130 _argvec[7] = (unsigned long)(arg7); \
6131 _argvec[8] = (unsigned long)(arg8); \
6132 _argvec[9] = (unsigned long)(arg9); \
6133 _argvec[10] = (unsigned long)(arg10); \
6134 _argvec[11] = (unsigned long)(arg11); \
6135 _argvec[12] = (unsigned long)(arg12); \
6136 __asm__ volatile( \
6137 "dsubu $29, $29, 32\n\t" \
6138 "ld $4, 72(%1)\n\t" \
6139 "sd $4, 0($29)\n\t" \
6140 "ld $4, 80(%1)\n\t" \
6141 "sd $4, 8($29)\n\t" \
6142 "ld $4, 88(%1)\n\t" \
6143 "sd $4, 16($29)\n\t" \
6144 "ld $4, 96(%1)\n\t" \
6145 "sd $4, 24($29)\n\t" \
6146 "ld $4, 8(%1)\n\t" \
6147 "ld $5, 16(%1)\n\t" \
6148 "ld $6, 24(%1)\n\t" \
6149 "ld $7, 32(%1)\n\t" \
6150 "ld $8, 40(%1)\n\t" \
6151 "ld $9, 48(%1)\n\t" \
6152 "ld $10, 56(%1)\n\t" \
6153 "ld $11, 64(%1)\n\t" \
6154 "ld $25, 0(%1)\n\t" /* target->t9 */ \
6155 VALGRIND_CALL_NOREDIR_T9 \
6156 "daddu $29, $29, 32\n\t" \
6157 "move %0, $2\n" \
6158 : /*out*/ "=r" (_res) \
6159 : /*in*/ "r" (&_argvec[0]) \
6160 : /*trash*/ "memory", __CALLER_SAVED_REGS \
6161 ); \
6162 lval = (__typeof__(lval)) _res; \
6163 } while (0)
6164
6165#endif /* PLAT_mips64_linux */
6166
sewardj112711a2015-04-10 12:30:09 +00006167/* ------------------------ tilegx-linux ------------------------- */
6168
6169#if defined(PLAT_tilegx_linux)
6170
6171/* These regs are trashed by the hidden call. */
6172#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3", "r4", "r5", \
6173 "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", \
6174 "r15", "r16", "r17", "r18", "r19", "r20", "r21", "r22", \
6175 "r23", "r24", "r25", "r26", "r27", "r28", "r29", "lr"
6176
6177/* These CALL_FN_ macros assume that on tilegx-linux, sizeof(unsigned
6178 long) == 8. */
6179
6180#define CALL_FN_W_v(lval, orig) \
6181 do { \
6182 volatile OrigFn _orig = (orig); \
6183 volatile unsigned long _argvec[1]; \
6184 volatile unsigned long _res; \
6185 _argvec[0] = (unsigned long)_orig.nraddr; \
6186 __asm__ volatile( \
6187 "addi sp, sp, -8 \n\t" \
6188 "st_add sp, lr, -8 \n\t" \
6189 "ld r12, %1 \n\t" /* target->r11 */ \
6190 VALGRIND_CALL_NOREDIR_R12 \
6191 "addi sp, sp, 8\n\t" \
6192 "ld_add lr, sp, 8 \n\t" \
6193 "move %0, r0 \n" \
6194 : /*out*/ "=r" (_res) \
6195 : /*in*/ "r" (&_argvec[0]) \
6196 : /*trash*/ "memory", __CALLER_SAVED_REGS); \
6197 \
6198 lval = (__typeof__(lval)) _res; \
6199 } while (0)
6200
6201#define CALL_FN_W_W(lval, orig, arg1) \
6202 do { \
6203 volatile OrigFn _orig = (orig); \
6204 volatile unsigned long _argvec[2]; \
6205 volatile unsigned long _res; \
6206 _argvec[0] = (unsigned long)_orig.nraddr; \
6207 _argvec[1] = (unsigned long)(arg1); \
6208 __asm__ volatile( \
6209 "addi sp, sp, -8 \n\t" \
6210 "st_add sp, lr, -8 \n\t" \
6211 "move r29, %1 \n\t" \
6212 "ld_add r12, r29, 8 \n\t" /* target->r11 */ \
6213 "ld_add r0, r29, 8 \n\t" /*arg1 -> r0 */ \
6214 VALGRIND_CALL_NOREDIR_R12 \
6215 "addi sp, sp, 8\n\t" \
6216 "ld_add lr, sp, 8 \n\t" \
6217 "move %0, r0\n" \
6218 : /*out*/ "=r" (_res) \
6219 : /*in*/ "r" (&_argvec[0]) \
6220 : /*trash*/ "memory", __CALLER_SAVED_REGS); \
6221 lval = (__typeof__(lval)) _res; \
6222 } while (0)
6223
6224#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
6225 do { \
6226 volatile OrigFn _orig = (orig); \
6227 volatile unsigned long _argvec[3]; \
6228 volatile unsigned long _res; \
6229 _argvec[0] = (unsigned long)_orig.nraddr; \
6230 _argvec[1] = (unsigned long)(arg1); \
6231 _argvec[2] = (unsigned long)(arg2); \
6232 __asm__ volatile( \
6233 "addi sp, sp, -8 \n\t" \
6234 "st_add sp, lr, -8 \n\t" \
6235 "move r29, %1 \n\t" \
6236 "ld_add r12, r29, 8 \n\t" /* target->r11 */ \
6237 "ld_add r0, r29, 8 \n\t" /*arg1 -> r0 */ \
6238 "ld_add r1, r29, 8 \n\t" /*arg2 -> r1 */ \
6239 VALGRIND_CALL_NOREDIR_R12 \
6240 "addi sp, sp, 8\n\t" \
6241 "ld_add lr, sp, 8 \n\t" \
6242 "move %0, r0\n" \
6243 : /*out*/ "=r" (_res) \
6244 : /*in*/ "r" (&_argvec[0]) \
6245 : /*trash*/ "memory", __CALLER_SAVED_REGS); \
6246 lval = (__typeof__(lval)) _res; \
6247 } while (0)
6248
6249#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
6250 do { \
6251 volatile OrigFn _orig = (orig); \
6252 volatile unsigned long _argvec[4]; \
6253 volatile unsigned long _res; \
6254 _argvec[0] = (unsigned long)_orig.nraddr; \
6255 _argvec[1] = (unsigned long)(arg1); \
6256 _argvec[2] = (unsigned long)(arg2); \
6257 _argvec[3] = (unsigned long)(arg3); \
6258 __asm__ volatile( \
6259 "addi sp, sp, -8 \n\t" \
6260 "st_add sp, lr, -8 \n\t" \
6261 "move r29, %1 \n\t" \
6262 "ld_add r12, r29, 8 \n\t" /* target->r11 */ \
6263 "ld_add r0, r29, 8 \n\t" /*arg1 -> r0 */ \
6264 "ld_add r1, r29, 8 \n\t" /*arg2 -> r1 */ \
6265 "ld_add r2, r29, 8 \n\t" /*arg3 -> r2 */ \
6266 VALGRIND_CALL_NOREDIR_R12 \
6267 "addi sp, sp, 8 \n\t" \
6268 "ld_add lr, sp, 8 \n\t" \
6269 "move %0, r0\n" \
6270 : /*out*/ "=r" (_res) \
6271 : /*in*/ "r" (&_argvec[0]) \
6272 : /*trash*/ "memory", __CALLER_SAVED_REGS); \
6273 lval = (__typeof__(lval)) _res; \
6274 } while (0)
6275
6276#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
6277 do { \
6278 volatile OrigFn _orig = (orig); \
6279 volatile unsigned long _argvec[5]; \
6280 volatile unsigned long _res; \
6281 _argvec[0] = (unsigned long)_orig.nraddr; \
6282 _argvec[1] = (unsigned long)(arg1); \
6283 _argvec[2] = (unsigned long)(arg2); \
6284 _argvec[3] = (unsigned long)(arg3); \
6285 _argvec[4] = (unsigned long)(arg4); \
6286 __asm__ volatile( \
6287 "addi sp, sp, -8 \n\t" \
6288 "st_add sp, lr, -8 \n\t" \
6289 "move r29, %1 \n\t" \
6290 "ld_add r12, r29, 8 \n\t" /* target->r11 */ \
6291 "ld_add r0, r29, 8 \n\t" /*arg1 -> r0 */ \
6292 "ld_add r1, r29, 8 \n\t" /*arg2 -> r1 */ \
6293 "ld_add r2, r29, 8 \n\t" /*arg3 -> r2 */ \
6294 "ld_add r3, r29, 8 \n\t" /*arg4 -> r3 */ \
6295 VALGRIND_CALL_NOREDIR_R12 \
6296 "addi sp, sp, 8\n\t" \
6297 "ld_add lr, sp, 8 \n\t" \
6298 "move %0, r0\n" \
6299 : /*out*/ "=r" (_res) \
6300 : /*in*/ "r" (&_argvec[0]) \
6301 : /*trash*/ "memory", __CALLER_SAVED_REGS); \
6302 lval = (__typeof__(lval)) _res; \
6303 } while (0)
6304
6305#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
6306 do { \
6307 volatile OrigFn _orig = (orig); \
6308 volatile unsigned long _argvec[6]; \
6309 volatile unsigned long _res; \
6310 _argvec[0] = (unsigned long)_orig.nraddr; \
6311 _argvec[1] = (unsigned long)(arg1); \
6312 _argvec[2] = (unsigned long)(arg2); \
6313 _argvec[3] = (unsigned long)(arg3); \
6314 _argvec[4] = (unsigned long)(arg4); \
6315 _argvec[5] = (unsigned long)(arg5); \
6316 __asm__ volatile( \
6317 "addi sp, sp, -8 \n\t" \
6318 "st_add sp, lr, -8 \n\t" \
6319 "move r29, %1 \n\t" \
6320 "ld_add r12, r29, 8 \n\t" /* target->r11 */ \
6321 "ld_add r0, r29, 8 \n\t" /*arg1 -> r0 */ \
6322 "ld_add r1, r29, 8 \n\t" /*arg2 -> r1 */ \
6323 "ld_add r2, r29, 8 \n\t" /*arg3 -> r2 */ \
6324 "ld_add r3, r29, 8 \n\t" /*arg4 -> r3 */ \
6325 "ld_add r4, r29, 8 \n\t" /*arg5 -> r4 */ \
6326 VALGRIND_CALL_NOREDIR_R12 \
6327 "addi sp, sp, 8\n\t" \
6328 "ld_add lr, sp, 8 \n\t" \
6329 "move %0, r0\n" \
6330 : /*out*/ "=r" (_res) \
6331 : /*in*/ "r" (&_argvec[0]) \
6332 : /*trash*/ "memory", __CALLER_SAVED_REGS); \
6333 lval = (__typeof__(lval)) _res; \
6334 } while (0)
6335#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
6336 do { \
6337 volatile OrigFn _orig = (orig); \
6338 volatile unsigned long _argvec[7]; \
6339 volatile unsigned long _res; \
6340 _argvec[0] = (unsigned long)_orig.nraddr; \
6341 _argvec[1] = (unsigned long)(arg1); \
6342 _argvec[2] = (unsigned long)(arg2); \
6343 _argvec[3] = (unsigned long)(arg3); \
6344 _argvec[4] = (unsigned long)(arg4); \
6345 _argvec[5] = (unsigned long)(arg5); \
6346 _argvec[6] = (unsigned long)(arg6); \
6347 __asm__ volatile( \
6348 "addi sp, sp, -8 \n\t" \
6349 "st_add sp, lr, -8 \n\t" \
6350 "move r29, %1 \n\t" \
6351 "ld_add r12, r29, 8 \n\t" /* target->r11 */ \
6352 "ld_add r0, r29, 8 \n\t" /*arg1 -> r0 */ \
6353 "ld_add r1, r29, 8 \n\t" /*arg2 -> r1 */ \
6354 "ld_add r2, r29, 8 \n\t" /*arg3 -> r2 */ \
6355 "ld_add r3, r29, 8 \n\t" /*arg4 -> r3 */ \
6356 "ld_add r4, r29, 8 \n\t" /*arg5 -> r4 */ \
6357 "ld_add r5, r29, 8 \n\t" /*arg6 -> r5 */ \
6358 VALGRIND_CALL_NOREDIR_R12 \
6359 "addi sp, sp, 8\n\t" \
6360 "ld_add lr, sp, 8 \n\t" \
6361 "move %0, r0\n" \
6362 : /*out*/ "=r" (_res) \
6363 : /*in*/ "r" (&_argvec[0]) \
6364 : /*trash*/ "memory", __CALLER_SAVED_REGS); \
6365 lval = (__typeof__(lval)) _res; \
6366 } while (0)
6367
6368#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
6369 arg7) \
6370 do { \
6371 volatile OrigFn _orig = (orig); \
6372 volatile unsigned long _argvec[8]; \
6373 volatile unsigned long _res; \
6374 _argvec[0] = (unsigned long)_orig.nraddr; \
6375 _argvec[1] = (unsigned long)(arg1); \
6376 _argvec[2] = (unsigned long)(arg2); \
6377 _argvec[3] = (unsigned long)(arg3); \
6378 _argvec[4] = (unsigned long)(arg4); \
6379 _argvec[5] = (unsigned long)(arg5); \
6380 _argvec[6] = (unsigned long)(arg6); \
6381 _argvec[7] = (unsigned long)(arg7); \
6382 __asm__ volatile( \
6383 "addi sp, sp, -8 \n\t" \
6384 "st_add sp, lr, -8 \n\t" \
6385 "move r29, %1 \n\t" \
6386 "ld_add r12, r29, 8 \n\t" /* target->r11 */ \
6387 "ld_add r0, r29, 8 \n\t" /*arg1 -> r0 */ \
6388 "ld_add r1, r29, 8 \n\t" /*arg2 -> r1 */ \
6389 "ld_add r2, r29, 8 \n\t" /*arg3 -> r2 */ \
6390 "ld_add r3, r29, 8 \n\t" /*arg4 -> r3 */ \
6391 "ld_add r4, r29, 8 \n\t" /*arg5 -> r4 */ \
6392 "ld_add r5, r29, 8 \n\t" /*arg6 -> r5 */ \
6393 "ld_add r6, r29, 8 \n\t" /*arg7 -> r6 */ \
6394 VALGRIND_CALL_NOREDIR_R12 \
6395 "addi sp, sp, 8\n\t" \
6396 "ld_add lr, sp, 8 \n\t" \
6397 "move %0, r0\n" \
6398 : /*out*/ "=r" (_res) \
6399 : /*in*/ "r" (&_argvec[0]) \
6400 : /*trash*/ "memory", __CALLER_SAVED_REGS); \
6401 lval = (__typeof__(lval)) _res; \
6402 } while (0)
6403
6404#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
6405 arg7,arg8) \
6406 do { \
6407 volatile OrigFn _orig = (orig); \
6408 volatile unsigned long _argvec[9]; \
6409 volatile unsigned long _res; \
6410 _argvec[0] = (unsigned long)_orig.nraddr; \
6411 _argvec[1] = (unsigned long)(arg1); \
6412 _argvec[2] = (unsigned long)(arg2); \
6413 _argvec[3] = (unsigned long)(arg3); \
6414 _argvec[4] = (unsigned long)(arg4); \
6415 _argvec[5] = (unsigned long)(arg5); \
6416 _argvec[6] = (unsigned long)(arg6); \
6417 _argvec[7] = (unsigned long)(arg7); \
6418 _argvec[8] = (unsigned long)(arg8); \
6419 __asm__ volatile( \
6420 "addi sp, sp, -8 \n\t" \
6421 "st_add sp, lr, -8 \n\t" \
6422 "move r29, %1 \n\t" \
6423 "ld_add r12, r29, 8 \n\t" /* target->r11 */ \
6424 "ld_add r0, r29, 8 \n\t" /*arg1 -> r0 */ \
6425 "ld_add r1, r29, 8 \n\t" /*arg2 -> r1 */ \
6426 "ld_add r2, r29, 8 \n\t" /*arg3 -> r2 */ \
6427 "ld_add r3, r29, 8 \n\t" /*arg4 -> r3 */ \
6428 "ld_add r4, r29, 8 \n\t" /*arg5 -> r4 */ \
6429 "ld_add r5, r29, 8 \n\t" /*arg6 -> r5 */ \
6430 "ld_add r6, r29, 8 \n\t" /*arg7 -> r6 */ \
6431 "ld_add r7, r29, 8 \n\t" /*arg8 -> r7 */ \
6432 VALGRIND_CALL_NOREDIR_R12 \
6433 "addi sp, sp, 8\n\t" \
6434 "ld_add lr, sp, 8 \n\t" \
6435 "move %0, r0\n" \
6436 : /*out*/ "=r" (_res) \
6437 : /*in*/ "r" (&_argvec[0]) \
6438 : /*trash*/ "memory", __CALLER_SAVED_REGS); \
6439 lval = (__typeof__(lval)) _res; \
6440 } while (0)
6441
6442#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
6443 arg7,arg8,arg9) \
6444 do { \
6445 volatile OrigFn _orig = (orig); \
6446 volatile unsigned long _argvec[10]; \
6447 volatile unsigned long _res; \
6448 _argvec[0] = (unsigned long)_orig.nraddr; \
6449 _argvec[1] = (unsigned long)(arg1); \
6450 _argvec[2] = (unsigned long)(arg2); \
6451 _argvec[3] = (unsigned long)(arg3); \
6452 _argvec[4] = (unsigned long)(arg4); \
6453 _argvec[5] = (unsigned long)(arg5); \
6454 _argvec[6] = (unsigned long)(arg6); \
6455 _argvec[7] = (unsigned long)(arg7); \
6456 _argvec[8] = (unsigned long)(arg8); \
6457 _argvec[9] = (unsigned long)(arg9); \
6458 __asm__ volatile( \
6459 "addi sp, sp, -8 \n\t" \
6460 "st_add sp, lr, -8 \n\t" \
6461 "move r29, %1 \n\t" \
6462 "ld_add r12, r29, 8 \n\t" /* target->r11 */ \
6463 "ld_add r0, r29, 8 \n\t" /*arg1 -> r0 */ \
6464 "ld_add r1, r29, 8 \n\t" /*arg2 -> r1 */ \
6465 "ld_add r2, r29, 8 \n\t" /*arg3 -> r2 */ \
6466 "ld_add r3, r29, 8 \n\t" /*arg4 -> r3 */ \
6467 "ld_add r4, r29, 8 \n\t" /*arg5 -> r4 */ \
6468 "ld_add r5, r29, 8 \n\t" /*arg6 -> r5 */ \
6469 "ld_add r6, r29, 8 \n\t" /*arg7 -> r6 */ \
6470 "ld_add r7, r29, 8 \n\t" /*arg8 -> r7 */ \
6471 "ld_add r8, r29, 8 \n\t" /*arg9 -> r8 */ \
6472 VALGRIND_CALL_NOREDIR_R12 \
6473 "addi sp, sp, 8\n\t" \
6474 "ld_add lr, sp, 8 \n\t" \
6475 "move %0, r0\n" \
6476 : /*out*/ "=r" (_res) \
6477 : /*in*/ "r" (&_argvec[0]) \
6478 : /*trash*/ "memory", __CALLER_SAVED_REGS); \
6479 lval = (__typeof__(lval)) _res; \
6480 } while (0)
6481
6482#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
6483 arg7,arg8,arg9,arg10) \
6484 do { \
6485 volatile OrigFn _orig = (orig); \
6486 volatile unsigned long _argvec[11]; \
6487 volatile unsigned long _res; \
6488 _argvec[0] = (unsigned long)_orig.nraddr; \
6489 _argvec[1] = (unsigned long)(arg1); \
6490 _argvec[2] = (unsigned long)(arg2); \
6491 _argvec[3] = (unsigned long)(arg3); \
6492 _argvec[4] = (unsigned long)(arg4); \
6493 _argvec[5] = (unsigned long)(arg5); \
6494 _argvec[6] = (unsigned long)(arg6); \
6495 _argvec[7] = (unsigned long)(arg7); \
6496 _argvec[8] = (unsigned long)(arg8); \
6497 _argvec[9] = (unsigned long)(arg9); \
6498 _argvec[10] = (unsigned long)(arg10); \
6499 __asm__ volatile( \
6500 "addi sp, sp, -8 \n\t" \
6501 "st_add sp, lr, -8 \n\t" \
6502 "move r29, %1 \n\t" \
6503 "ld_add r12, r29, 8 \n\t" /* target->r11 */ \
6504 "ld_add r0, r29, 8 \n\t" /*arg1 -> r0 */ \
6505 "ld_add r1, r29, 8 \n\t" /*arg2 -> r1 */ \
6506 "ld_add r2, r29, 8 \n\t" /*arg3 -> r2 */ \
6507 "ld_add r3, r29, 8 \n\t" /*arg4 -> r3 */ \
6508 "ld_add r4, r29, 8 \n\t" /*arg5 -> r4 */ \
6509 "ld_add r5, r29, 8 \n\t" /*arg6 -> r5 */ \
6510 "ld_add r6, r29, 8 \n\t" /*arg7 -> r6 */ \
6511 "ld_add r7, r29, 8 \n\t" /*arg8 -> r7 */ \
6512 "ld_add r8, r29, 8 \n\t" /*arg9 -> r8 */ \
6513 "ld_add r9, r29, 8 \n\t" /*arg10 -> r9 */ \
6514 VALGRIND_CALL_NOREDIR_R12 \
6515 "addi sp, sp, 8\n\t" \
6516 "ld_add lr, sp, 8 \n\t" \
6517 "move %0, r0\n" \
6518 : /*out*/ "=r" (_res) \
6519 : /*in*/ "r" (&_argvec[0]) \
6520 : /*trash*/ "memory", __CALLER_SAVED_REGS); \
6521 lval = (__typeof__(lval)) _res; \
6522 } while (0)
6523
6524#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
6525 arg6,arg7,arg8,arg9,arg10, \
6526 arg11) \
6527 do { \
6528 volatile OrigFn _orig = (orig); \
6529 volatile unsigned long _argvec[12]; \
6530 volatile unsigned long _res; \
6531 _argvec[0] = (unsigned long)_orig.nraddr; \
6532 _argvec[1] = (unsigned long)(arg1); \
6533 _argvec[2] = (unsigned long)(arg2); \
6534 _argvec[3] = (unsigned long)(arg3); \
6535 _argvec[4] = (unsigned long)(arg4); \
6536 _argvec[5] = (unsigned long)(arg5); \
6537 _argvec[6] = (unsigned long)(arg6); \
6538 _argvec[7] = (unsigned long)(arg7); \
6539 _argvec[8] = (unsigned long)(arg8); \
6540 _argvec[9] = (unsigned long)(arg9); \
6541 _argvec[10] = (unsigned long)(arg10); \
6542 _argvec[11] = (unsigned long)(arg11); \
6543 __asm__ volatile( \
6544 "addi sp, sp, -8 \n\t" \
6545 "st_add sp, lr, -8 \n\t" \
6546 "move r29, %1 \n\t" \
6547 "ld_add r12, r29, 8 \n\t" /* target->r11 */ \
6548 "ld_add r0, r29, 8 \n\t" /*arg1 -> r0 */ \
6549 "ld_add r1, r29, 8 \n\t" /*arg2 -> r1 */ \
6550 "ld_add r2, r29, 8 \n\t" /*arg3 -> r2 */ \
6551 "ld_add r3, r29, 8 \n\t" /*arg4 -> r3 */ \
6552 "ld_add r4, r29, 8 \n\t" /*arg5 -> r4 */ \
6553 "ld_add r5, r29, 8 \n\t" /*arg6 -> r5 */ \
6554 "ld_add r6, r29, 8 \n\t" /*arg7 -> r6 */ \
6555 "ld_add r7, r29, 8 \n\t" /*arg8 -> r7 */ \
6556 "ld_add r8, r29, 8 \n\t" /*arg9 -> r8 */ \
6557 "ld_add r9, r29, 8 \n\t" /*arg10 -> r9 */ \
6558 "ld r10, r29 \n\t" \
6559 "st_add sp, r10, -16 \n\t" \
6560 VALGRIND_CALL_NOREDIR_R12 \
6561 "addi sp, sp, 24 \n\t" \
6562 "ld_add lr, sp, 8 \n\t" \
6563 "move %0, r0\n" \
6564 : /*out*/ "=r" (_res) \
6565 : /*in*/ "r" (&_argvec[0]) \
6566 : /*trash*/ "memory", __CALLER_SAVED_REGS); \
6567 lval = (__typeof__(lval)) _res; \
6568 } while (0)
6569
6570#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
6571 arg6,arg7,arg8,arg9,arg10, \
6572 arg11,arg12) \
6573 do { \
6574 volatile OrigFn _orig = (orig); \
6575 volatile unsigned long _argvec[13]; \
6576 volatile unsigned long _res; \
6577 _argvec[0] = (unsigned long)_orig.nraddr; \
6578 _argvec[1] = (unsigned long)(arg1); \
6579 _argvec[2] = (unsigned long)(arg2); \
6580 _argvec[3] = (unsigned long)(arg3); \
6581 _argvec[4] = (unsigned long)(arg4); \
6582 _argvec[5] = (unsigned long)(arg5); \
6583 _argvec[6] = (unsigned long)(arg6); \
6584 _argvec[7] = (unsigned long)(arg7); \
6585 _argvec[8] = (unsigned long)(arg8); \
6586 _argvec[9] = (unsigned long)(arg9); \
6587 _argvec[10] = (unsigned long)(arg10); \
6588 _argvec[11] = (unsigned long)(arg11); \
6589 _argvec[12] = (unsigned long)(arg12); \
6590 __asm__ volatile( \
6591 "addi sp, sp, -8 \n\t" \
6592 "st_add sp, lr, -8 \n\t" \
6593 "move r29, %1 \n\t" \
6594 "ld_add r12, r29, 8 \n\t" /* target->r11 */ \
6595 "ld_add r0, r29, 8 \n\t" /*arg1 -> r0 */ \
6596 "ld_add r1, r29, 8 \n\t" /*arg2 -> r1 */ \
6597 "ld_add r2, r29, 8 \n\t" /*arg3 -> r2 */ \
6598 "ld_add r3, r29, 8 \n\t" /*arg4 -> r3 */ \
6599 "ld_add r4, r29, 8 \n\t" /*arg5 -> r4 */ \
6600 "ld_add r5, r29, 8 \n\t" /*arg6 -> r5 */ \
6601 "ld_add r6, r29, 8 \n\t" /*arg7 -> r6 */ \
6602 "ld_add r7, r29, 8 \n\t" /*arg8 -> r7 */ \
6603 "ld_add r8, r29, 8 \n\t" /*arg9 -> r8 */ \
6604 "ld_add r9, r29, 8 \n\t" /*arg10 -> r9 */ \
6605 "addi r28, sp, -8 \n\t" \
6606 "addi sp, sp, -24 \n\t" \
6607 "ld_add r10, r29, 8 \n\t" \
6608 "ld r11, r29 \n\t" \
6609 "st_add r28, r10, 8 \n\t" \
6610 "st r28, r11 \n\t" \
6611 VALGRIND_CALL_NOREDIR_R12 \
6612 "addi sp, sp, 32 \n\t" \
6613 "ld_add lr, sp, 8 \n\t" \
6614 "move %0, r0\n" \
6615 : /*out*/ "=r" (_res) \
6616 : /*in*/ "r" (&_argvec[0]) \
6617 : /*trash*/ "memory", __CALLER_SAVED_REGS); \
6618 lval = (__typeof__(lval)) _res; \
6619 } while (0)
6620#endif /* PLAT_tilegx_linux */
sewardj0ec07f32006-01-12 12:32:32 +00006621
6622/* ------------------------------------------------------------------ */
6623/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
6624/* */
njn30d76c62005-06-18 15:07:39 +00006625/* ------------------------------------------------------------------ */
6626
sewardj2e93c502002-04-12 11:12:52 +00006627/* Some request codes. There are many more of these, but most are not
6628 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00006629 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00006630
sewardj0ec07f32006-01-12 12:32:32 +00006631 Core ones are in the range 0x00000000--0x0000ffff. The non-public
6632 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00006633*/
6634
sewardj0ec07f32006-01-12 12:32:32 +00006635/* These macros are used by tools -- they must be public, but don't
6636 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00006637#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00006638 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00006639#define VG_IS_TOOL_USERREQ(a, b, v) \
6640 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00006641
sewardj5ce4b152006-03-11 12:57:41 +00006642/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
6643 This enum comprises an ABI exported by Valgrind to programs
6644 which use client requests. DO NOT CHANGE THE ORDER OF THESE
6645 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00006646typedef
njn4c791212003-05-02 17:53:54 +00006647 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
6648 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00006649
sewardj0ec07f32006-01-12 12:32:32 +00006650 /* These allow any function to be called from the simulated
6651 CPU but run on the real CPU. Nb: the first arg passed to
6652 the function is always the ThreadId of the running
6653 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00006654 function, etc. */
njn4c791212003-05-02 17:53:54 +00006655 VG_USERREQ__CLIENT_CALL0 = 0x1101,
6656 VG_USERREQ__CLIENT_CALL1 = 0x1102,
6657 VG_USERREQ__CLIENT_CALL2 = 0x1103,
6658 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00006659
sewardj0ec07f32006-01-12 12:32:32 +00006660 /* Can be useful in regression testing suites -- eg. can
6661 send Valgrind's output to /dev/null and still count
6662 errors. */
njn4c791212003-05-02 17:53:54 +00006663 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00006664
philippe46207652013-01-20 17:11:58 +00006665 /* Allows the client program and/or gdbserver to execute a monitor
6666 command. */
sewardj3b290482011-05-06 21:02:55 +00006667 VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
6668
sewardj0ec07f32006-01-12 12:32:32 +00006669 /* These are useful and can be interpreted by any tool that
6670 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00006671 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
bart91347382011-03-25 20:07:25 +00006672 VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
njnd7994182003-10-02 13:44:04 +00006673 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00006674 /* Memory pool support. */
6675 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
6676 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
6677 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
6678 VG_USERREQ__MEMPOOL_FREE = 0x1306,
sewardj2c1c9df2006-07-28 00:06:37 +00006679 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
sewardjc740d762006-10-05 17:59:23 +00006680 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
6681 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
6682 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
njnd7994182003-10-02 13:44:04 +00006683
fitzhardinge39de4b42003-10-31 07:12:21 +00006684 /* Allow printfs to valgrind log. */
sewardjc560fb32010-01-28 15:23:54 +00006685 /* The first two pass the va_list argument by value, which
6686 assumes it is the same size as or smaller than a UWord,
6687 which generally isn't the case. Hence are deprecated.
6688 The second two pass the vargs by reference and so are
6689 immune to this problem. */
6690 /* both :: char* fmt, va_list vargs (DEPRECATED) */
njn30d76c62005-06-18 15:07:39 +00006691 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00006692 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
sewardjc560fb32010-01-28 15:23:54 +00006693 /* both :: char* fmt, va_list* vargs */
6694 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
6695 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
rjwalsh0140af52005-06-04 20:42:33 +00006696
6697 /* Stack support. */
6698 VG_USERREQ__STACK_REGISTER = 0x1501,
6699 VG_USERREQ__STACK_DEREGISTER = 0x1502,
sewardjc8259b82009-04-22 22:42:10 +00006700 VG_USERREQ__STACK_CHANGE = 0x1503,
6701
6702 /* Wine support */
sewardj5c659622010-08-20 18:22:07 +00006703 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
6704
6705 /* Querying of debug info. */
sewardjdc873c02011-07-24 16:02:33 +00006706 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
6707
6708 /* Disable/enable error reporting level. Takes a single
6709 Word arg which is the delta to this thread's error
6710 disablement indicator. Hence 1 disables or further
6711 disables errors, and -1 moves back towards enablement.
6712 Other values are not allowed. */
florianbb913cd2012-08-28 16:50:39 +00006713 VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801,
6714
6715 /* Initialise IR injection */
6716 VG_USERREQ__VEX_INIT_FOR_IRI = 0x1901
njn25e49d8e72002-09-23 09:36:25 +00006717 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00006718
sewardj0ec07f32006-01-12 12:32:32 +00006719#if !defined(__GNUC__)
6720# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00006721#endif
sewardj2e93c502002-04-12 11:12:52 +00006722
bartfa5115a2010-09-02 09:33:02 +00006723
sewardj0ec07f32006-01-12 12:32:32 +00006724/* Returns the number of Valgrinds this code is running under. That
6725 is, 0 if running natively, 1 if running under Valgrind, 2 if
6726 running under Valgrind which is running under another Valgrind,
6727 etc. */
bartfa5115a2010-09-02 09:33:02 +00006728#define RUNNING_ON_VALGRIND \
bart575ce8e2011-05-15 07:04:03 +00006729 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \
bartfa5115a2010-09-02 09:33:02 +00006730 VG_USERREQ__RUNNING_ON_VALGRIND, \
6731 0, 0, 0, 0, 0) \
sewardjde4a1d02002-03-22 01:27:54 +00006732
6733
sewardj18d75132002-05-16 11:06:21 +00006734/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
6735 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
6736 since it provides a way to make sure valgrind will retranslate the
6737 invalidated area. Returns no value. */
sewardj4b3a7422011-10-24 13:21:57 +00006738#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
6739 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DISCARD_TRANSLATIONS, \
6740 _qzz_addr, _qzz_len, 0, 0, 0)
sewardj18d75132002-05-16 11:06:21 +00006741
njn26aba4d2005-05-16 13:31:23 +00006742
sewardj0ec07f32006-01-12 12:32:32 +00006743/* These requests are for getting Valgrind itself to print something.
njnd55f0d92009-08-03 01:38:56 +00006744 Possibly with a backtrace. This is a really ugly hack. The return value
6745 is the number of characters printed, excluding the "**<pid>** " part at the
6746 start and the backtrace (if present). */
sewardj0ec07f32006-01-12 12:32:32 +00006747
bart42f83fe2012-01-31 10:13:51 +00006748#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00006749/* Modern GCC will optimize the static routine out if unused,
6750 and unused attribute will shut down warnings about it. */
6751static int VALGRIND_PRINTF(const char *format, ...)
6752 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00006753#endif
sewardj7eca0cc2006-04-12 17:15:35 +00006754static int
bart0da2c772010-09-01 10:18:36 +00006755#if defined(_MSC_VER)
6756__inline
6757#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00006758VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00006759{
bart8c7e25f2011-03-04 16:55:56 +00006760#if defined(NVALGRIND)
6761 return 0;
6762#else /* NVALGRIND */
bartaaaf21d2013-08-25 06:10:24 +00006763#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00006764 uintptr_t _qzz_res;
6765#else
njnc6168192004-11-29 13:54:10 +00006766 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00006767#endif
sewardjc560fb32010-01-28 15:23:54 +00006768 va_list vargs;
6769 va_start(vargs, format);
bartaaaf21d2013-08-25 06:10:24 +00006770#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00006771 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00006772 VG_USERREQ__PRINTF_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00006773 (uintptr_t)format,
6774 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00006775 0, 0, 0);
6776#else
bart575ce8e2011-05-15 07:04:03 +00006777 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00006778 VG_USERREQ__PRINTF_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00006779 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00006780 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00006781 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00006782#endif
sewardjc560fb32010-01-28 15:23:54 +00006783 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00006784 return (int)_qzz_res;
bart8c7e25f2011-03-04 16:55:56 +00006785#endif /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00006786}
6787
bart42f83fe2012-01-31 10:13:51 +00006788#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00006789static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
6790 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00006791#endif
sewardj7eca0cc2006-04-12 17:15:35 +00006792static int
bart0da2c772010-09-01 10:18:36 +00006793#if defined(_MSC_VER)
6794__inline
6795#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00006796VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00006797{
bart8c7e25f2011-03-04 16:55:56 +00006798#if defined(NVALGRIND)
6799 return 0;
6800#else /* NVALGRIND */
bartaaaf21d2013-08-25 06:10:24 +00006801#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00006802 uintptr_t _qzz_res;
6803#else
njnc6168192004-11-29 13:54:10 +00006804 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00006805#endif
sewardjc560fb32010-01-28 15:23:54 +00006806 va_list vargs;
6807 va_start(vargs, format);
bartaaaf21d2013-08-25 06:10:24 +00006808#if defined(_MSC_VER) || defined(__MINGW64__)
bart575ce8e2011-05-15 07:04:03 +00006809 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00006810 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00006811 (uintptr_t)format,
6812 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00006813 0, 0, 0);
6814#else
bart575ce8e2011-05-15 07:04:03 +00006815 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00006816 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00006817 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00006818 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00006819 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00006820#endif
sewardjc560fb32010-01-28 15:23:54 +00006821 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00006822 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00006823#endif /* NVALGRIND */
bart8c7e25f2011-03-04 16:55:56 +00006824}
sewardj18d75132002-05-16 11:06:21 +00006825
sewardj0ec07f32006-01-12 12:32:32 +00006826
njn3e884182003-04-15 13:03:23 +00006827/* These requests allow control to move from the simulated CPU to the
njn1319b492006-11-20 22:02:40 +00006828 real CPU, calling an arbitary function.
6829
6830 Note that the current ThreadId is inserted as the first argument.
6831 So this call:
6832
6833 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
6834
6835 requires f to have this signature:
6836
6837 Word f(Word tid, Word arg1, Word arg2)
6838
6839 where "Word" is a word-sized type.
njn45fb4d32007-12-05 21:51:50 +00006840
6841 Note that these client requests are not entirely reliable. For example,
6842 if you call a function with them that subsequently calls printf(),
6843 there's a high chance Valgrind will crash. Generally, your prospects of
6844 these working are made higher if the called function does not refer to
6845 any global variables, and does not refer to any libc or other functions
6846 (printf et al). Any kind of entanglement with libc or dynamic linking is
6847 likely to have a bad outcome, for tricky reasons which we've grappled
6848 with a lot in the past.
njn1319b492006-11-20 22:02:40 +00006849*/
sewardj0ec07f32006-01-12 12:32:32 +00006850#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
bart575ce8e2011-05-15 07:04:03 +00006851 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
6852 VG_USERREQ__CLIENT_CALL0, \
6853 _qyy_fn, \
6854 0, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00006855
bart575ce8e2011-05-15 07:04:03 +00006856#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
6857 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
6858 VG_USERREQ__CLIENT_CALL1, \
6859 _qyy_fn, \
6860 _qyy_arg1, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00006861
bart575ce8e2011-05-15 07:04:03 +00006862#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
6863 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
6864 VG_USERREQ__CLIENT_CALL2, \
6865 _qyy_fn, \
6866 _qyy_arg1, _qyy_arg2, 0, 0)
njn3e884182003-04-15 13:03:23 +00006867
sewardj0ec07f32006-01-12 12:32:32 +00006868#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
bart575ce8e2011-05-15 07:04:03 +00006869 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
6870 VG_USERREQ__CLIENT_CALL3, \
6871 _qyy_fn, \
6872 _qyy_arg1, _qyy_arg2, \
6873 _qyy_arg3, 0)
njn3e884182003-04-15 13:03:23 +00006874
6875
nethercote7cc9c232004-01-21 15:08:04 +00006876/* Counts the number of errors that have been recorded by a tool. Nb:
6877 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00006878 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00006879#define VALGRIND_COUNT_ERRORS \
bart575ce8e2011-05-15 07:04:03 +00006880 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR( \
6881 0 /* default return */, \
sewardj0ec07f32006-01-12 12:32:32 +00006882 VG_USERREQ__COUNT_ERRORS, \
bart575ce8e2011-05-15 07:04:03 +00006883 0, 0, 0, 0, 0)
njn47363ab2003-04-21 13:24:40 +00006884
njn3ac96952009-07-09 23:35:44 +00006885/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
6886 when heap blocks are allocated in order to give accurate results. This
6887 happens automatically for the standard allocator functions such as
6888 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
6889 delete[], etc.
njnd7994182003-10-02 13:44:04 +00006890
njn3ac96952009-07-09 23:35:44 +00006891 But if your program uses a custom allocator, this doesn't automatically
6892 happen, and Valgrind will not do as well. For example, if you allocate
6893 superblocks with mmap() and then allocates chunks of the superblocks, all
6894 Valgrind's observations will be at the mmap() level and it won't know that
6895 the chunks should be considered separate entities. In Memcheck's case,
6896 that means you probably won't get heap block overrun detection (because
6897 there won't be redzones marked as unaddressable) and you definitely won't
6898 get any leak detection.
6899
6900 The following client requests allow a custom allocator to be annotated so
6901 that it can be handled accurately by Valgrind.
6902
6903 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
6904 by a malloc()-like function. For Memcheck (an illustrative case), this
6905 does two things:
6906
6907 - It records that the block has been allocated. This means any addresses
6908 within the block mentioned in error messages will be
6909 identified as belonging to the block. It also means that if the block
6910 isn't freed it will be detected by the leak checker.
6911
6912 - It marks the block as being addressable and undefined (if 'is_zeroed' is
6913 not set), or addressable and defined (if 'is_zeroed' is set). This
6914 controls how accesses to the block by the program are handled.
6915
6916 'addr' is the start of the usable block (ie. after any
6917 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
6918 can apply redzones -- these are blocks of padding at the start and end of
6919 each block. Adding redzones is recommended as it makes it much more likely
6920 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
6921 zeroed (or filled with another predictable value), as is the case for
6922 calloc().
6923
6924 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
6925 heap block -- that will be used by the client program -- is allocated.
6926 It's best to put it at the outermost level of the allocator if possible;
6927 for example, if you have a function my_alloc() which calls
6928 internal_alloc(), and the client request is put inside internal_alloc(),
6929 stack traces relating to the heap block will contain entries for both
6930 my_alloc() and internal_alloc(), which is probably not what you want.
6931
njnb965efb2009-08-10 07:36:54 +00006932 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
6933 custom blocks from within a heap block, B, that has been allocated with
6934 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
6935 -- the custom blocks will take precedence.
6936
njn3ac96952009-07-09 23:35:44 +00006937 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
6938 Memcheck, it does two things:
6939
6940 - It records that the block has been deallocated. This assumes that the
6941 block was annotated as having been allocated via
6942 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
6943
6944 - It marks the block as being unaddressable.
6945
6946 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
6947 heap block is deallocated.
6948
bart91347382011-03-25 20:07:25 +00006949 VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For
6950 Memcheck, it does four things:
6951
6952 - It records that the size of a block has been changed. This assumes that
6953 the block was annotated as having been allocated via
6954 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
6955
6956 - If the block shrunk, it marks the freed memory as being unaddressable.
6957
6958 - If the block grew, it marks the new area as undefined and defines a red
6959 zone past the end of the new block.
6960
6961 - The V-bits of the overlap between the old and the new block are preserved.
6962
6963 VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block
6964 and before deallocation of the old block.
6965
6966 In many cases, these three client requests will not be enough to get your
njn3ac96952009-07-09 23:35:44 +00006967 allocator working well with Memcheck. More specifically, if your allocator
6968 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
6969 will be necessary to mark the memory as addressable just before the zeroing
6970 occurs, otherwise you'll get a lot of invalid write errors. For example,
6971 you'll need to do this if your allocator recycles freed blocks, but it
6972 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
6973 Alternatively, if your allocator reuses freed blocks for allocator-internal
6974 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
6975
6976 Really, what's happening is a blurring of the lines between the client
6977 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
6978 memory should be considered unaddressable to the client program, but the
6979 allocator knows more than the rest of the client program and so may be able
6980 to safely access it. Extra client requests are necessary for Valgrind to
6981 understand the distinction between the allocator and the rest of the
6982 program.
6983
njn32f8d8c2009-07-15 02:31:45 +00006984 Ignored if addr == 0.
njn3ac96952009-07-09 23:35:44 +00006985*/
sewardj4b3a7422011-10-24 13:21:57 +00006986#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
6987 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MALLOCLIKE_BLOCK, \
6988 addr, sizeB, rzB, is_zeroed, 0)
njnd7994182003-10-02 13:44:04 +00006989
njn32f8d8c2009-07-15 02:31:45 +00006990/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
6991 Ignored if addr == 0.
6992*/
sewardj4b3a7422011-10-24 13:21:57 +00006993#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \
6994 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RESIZEINPLACE_BLOCK, \
6995 addr, oldSizeB, newSizeB, rzB, 0)
bart91347382011-03-25 20:07:25 +00006996
6997/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
6998 Ignored if addr == 0.
6999*/
sewardj4b3a7422011-10-24 13:21:57 +00007000#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
7001 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREELIKE_BLOCK, \
7002 addr, rzB, 0, 0, 0)
njnd7994182003-10-02 13:44:04 +00007003
rjwalshbc0bb832004-06-19 18:12:36 +00007004/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00007005#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
sewardj4b3a7422011-10-24 13:21:57 +00007006 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \
7007 pool, rzB, is_zeroed, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00007008
7009/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00007010#define VALGRIND_DESTROY_MEMPOOL(pool) \
sewardj4b3a7422011-10-24 13:21:57 +00007011 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DESTROY_MEMPOOL, \
7012 pool, 0, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00007013
7014/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00007015#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
sewardj4b3a7422011-10-24 13:21:57 +00007016 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_ALLOC, \
7017 pool, addr, size, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00007018
7019/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00007020#define VALGRIND_MEMPOOL_FREE(pool, addr) \
sewardj4b3a7422011-10-24 13:21:57 +00007021 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_FREE, \
7022 pool, addr, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00007023
sewardj2c1c9df2006-07-28 00:06:37 +00007024/* Disassociate any pieces outside a particular range. */
7025#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
sewardj4b3a7422011-10-24 13:21:57 +00007026 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_TRIM, \
7027 pool, addr, size, 0, 0)
sewardj2c1c9df2006-07-28 00:06:37 +00007028
sewardjc740d762006-10-05 17:59:23 +00007029/* Resize and/or move a piece associated with a memory pool. */
7030#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
sewardj4b3a7422011-10-24 13:21:57 +00007031 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MOVE_MEMPOOL, \
7032 poolA, poolB, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00007033
7034/* Resize and/or move a piece associated with a memory pool. */
7035#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
sewardj4b3a7422011-10-24 13:21:57 +00007036 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_CHANGE, \
7037 pool, addrA, addrB, size, 0)
sewardjc740d762006-10-05 17:59:23 +00007038
7039/* Return 1 if a mempool exists, else 0. */
7040#define VALGRIND_MEMPOOL_EXISTS(pool) \
bart575ce8e2011-05-15 07:04:03 +00007041 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardjc740d762006-10-05 17:59:23 +00007042 VG_USERREQ__MEMPOOL_EXISTS, \
bart575ce8e2011-05-15 07:04:03 +00007043 pool, 0, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00007044
philippe38a74d22014-08-29 22:53:19 +00007045/* Mark a piece of memory as being a stack. Returns a stack id.
7046 start is the lowest addressable stack byte, end is the highest
7047 addressable stack byte. */
sewardj0ec07f32006-01-12 12:32:32 +00007048#define VALGRIND_STACK_REGISTER(start, end) \
bart575ce8e2011-05-15 07:04:03 +00007049 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00007050 VG_USERREQ__STACK_REGISTER, \
bart575ce8e2011-05-15 07:04:03 +00007051 start, end, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00007052
7053/* Unmark the piece of memory associated with a stack id as being a
7054 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00007055#define VALGRIND_STACK_DEREGISTER(id) \
sewardj4b3a7422011-10-24 13:21:57 +00007056 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_DEREGISTER, \
7057 id, 0, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00007058
philippe38a74d22014-08-29 22:53:19 +00007059/* Change the start and end address of the stack id.
7060 start is the new lowest addressable stack byte, end is the new highest
7061 addressable stack byte. */
sewardj0ec07f32006-01-12 12:32:32 +00007062#define VALGRIND_STACK_CHANGE(id, start, end) \
sewardj4b3a7422011-10-24 13:21:57 +00007063 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_CHANGE, \
7064 id, start, end, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00007065
sewardjc8259b82009-04-22 22:42:10 +00007066/* Load PDB debug info for Wine PE image_map. */
sewardj4b3a7422011-10-24 13:21:57 +00007067#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
7068 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LOAD_PDB_DEBUGINFO, \
7069 fd, ptr, total_size, delta, 0)
sewardjc8259b82009-04-22 22:42:10 +00007070
sewardj5c659622010-08-20 18:22:07 +00007071/* Map a code address to a source file name and line number. buf64
7072 must point to a 64-byte buffer in the caller's address space. The
7073 result will be dumped in there and is guaranteed to be zero
7074 terminated. If no info is found, the first byte is set to zero. */
7075#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \
bart575ce8e2011-05-15 07:04:03 +00007076 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj5c659622010-08-20 18:22:07 +00007077 VG_USERREQ__MAP_IP_TO_SRCLOC, \
bart575ce8e2011-05-15 07:04:03 +00007078 addr, buf64, 0, 0, 0)
sewardj5c659622010-08-20 18:22:07 +00007079
sewardjdc873c02011-07-24 16:02:33 +00007080/* Disable error reporting for this thread. Behaves in a stack like
7081 way, so you can safely call this multiple times provided that
7082 VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times
7083 to re-enable reporting. The first call of this macro disables
7084 reporting. Subsequent calls have no effect except to increase the
7085 number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable
7086 reporting. Child threads do not inherit this setting from their
7087 parents -- they are always created with reporting enabled. */
bart06e9bf02011-10-07 09:39:56 +00007088#define VALGRIND_DISABLE_ERROR_REPORTING \
sewardj4b3a7422011-10-24 13:21:57 +00007089 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
7090 1, 0, 0, 0, 0)
sewardjdc873c02011-07-24 16:02:33 +00007091
7092/* Re-enable error reporting, as per comments on
7093 VALGRIND_DISABLE_ERROR_REPORTING. */
bart06e9bf02011-10-07 09:39:56 +00007094#define VALGRIND_ENABLE_ERROR_REPORTING \
sewardj4b3a7422011-10-24 13:21:57 +00007095 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
7096 -1, 0, 0, 0, 0)
sewardj0ec07f32006-01-12 12:32:32 +00007097
philippe46207652013-01-20 17:11:58 +00007098/* Execute a monitor command from the client program.
7099 If a connection is opened with GDB, the output will be sent
7100 according to the output mode set for vgdb.
7101 If no connection is opened, output will go to the log output.
7102 Returns 1 if command not recognised, 0 otherwise. */
7103#define VALGRIND_MONITOR_COMMAND(command) \
7104 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__GDB_MONITOR_COMMAND, \
7105 command, 0, 0, 0, 0)
7106
7107
sewardjc112c8e2011-06-24 18:26:11 +00007108#undef PLAT_x86_darwin
7109#undef PLAT_amd64_darwin
7110#undef PLAT_x86_win32
bartaaaf21d2013-08-25 06:10:24 +00007111#undef PLAT_amd64_win64
sewardjf5c1a7f2006-10-17 01:32:48 +00007112#undef PLAT_x86_linux
7113#undef PLAT_amd64_linux
7114#undef PLAT_ppc32_linux
carllcae0cc22014-08-07 23:17:29 +00007115#undef PLAT_ppc64be_linux
carll582d5822014-08-07 23:35:54 +00007116#undef PLAT_ppc64le_linux
sewardj59570ff2010-01-01 11:59:33 +00007117#undef PLAT_arm_linux
sewardjb5b87402011-03-07 16:05:35 +00007118#undef PLAT_s390x_linux
sewardj5db15402012-06-07 09:13:21 +00007119#undef PLAT_mips32_linux
petarj4df0bfc2013-02-27 23:17:33 +00007120#undef PLAT_mips64_linux
sewardj112711a2015-04-10 12:30:09 +00007121#undef PLAT_tilegx_linux
sewardj8eb8bab2015-07-21 14:44:28 +00007122#undef PLAT_x86_solaris
7123#undef PLAT_amd64_solaris
sewardj0ec07f32006-01-12 12:32:32 +00007124
njn3e884182003-04-15 13:03:23 +00007125#endif /* __VALGRIND_H */