blob: 38e47f469f8674ac9591366c979d52583ca7facf [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
sewardj03f8d3f2012-08-05 15:46:46 +000015 Copyright (C) 2000-2012 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
sewardj7d79e0b2012-05-21 21:57:05 +000092#define __VALGRIND_MINOR__ 8
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
sewardjf5c1a7f2006-10-17 01:32:48 +0000114#undef PLAT_x86_linux
115#undef PLAT_amd64_linux
116#undef PLAT_ppc32_linux
117#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +0000118#undef PLAT_arm_linux
sewardjb5b87402011-03-07 16:05:35 +0000119#undef PLAT_s390x_linux
sewardj5db15402012-06-07 09:13:21 +0000120#undef PLAT_mips32_linux
sewardjb5b87402011-03-07 16:05:35 +0000121
sewardj0ec07f32006-01-12 12:32:32 +0000122
sewardj6e9de462011-06-28 07:25:29 +0000123#if defined(__APPLE__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000124# define PLAT_x86_darwin 1
125#elif defined(__APPLE__) && defined(__x86_64__)
126# define PLAT_amd64_darwin 1
sewardj6e9de462011-06-28 07:25:29 +0000127#elif defined(__MINGW32__) || defined(__CYGWIN32__) \
128 || (defined(_WIN32) && defined(_M_IX86))
bart7f489812010-08-27 10:05:27 +0000129# define PLAT_x86_win32 1
sewardj59570ff2010-01-01 11:59:33 +0000130#elif defined(__linux__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000131# define PLAT_x86_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000132#elif defined(__linux__) && defined(__x86_64__)
njnf76d27a2009-05-28 01:53:07 +0000133# define PLAT_amd64_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000134#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000135# define PLAT_ppc32_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000136#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000137# define PLAT_ppc64_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000138#elif defined(__linux__) && defined(__arm__)
139# define PLAT_arm_linux 1
sewardjb5b87402011-03-07 16:05:35 +0000140#elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
141# define PLAT_s390x_linux 1
sewardj5db15402012-06-07 09:13:21 +0000142#elif defined(__linux__) && defined(__mips__)
143# define PLAT_mips32_linux 1
njnf76d27a2009-05-28 01:53:07 +0000144#else
sewardjf5c1a7f2006-10-17 01:32:48 +0000145/* If we're not compiling for our target platform, don't generate
sewardj0ec07f32006-01-12 12:32:32 +0000146 any inline asms. */
sewardj0ec07f32006-01-12 12:32:32 +0000147# if !defined(NVALGRIND)
148# define NVALGRIND 1
149# endif
150#endif
151
152
njn30d76c62005-06-18 15:07:39 +0000153/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000154/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
155/* in here of use to end-users -- skip to the next section. */
njn30d76c62005-06-18 15:07:39 +0000156/* ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000157
bart575ce8e2011-05-15 07:04:03 +0000158/*
159 * VALGRIND_DO_CLIENT_REQUEST(): a statement that invokes a Valgrind client
160 * request. Accepts both pointers and integers as arguments.
161 *
sewardj4b3a7422011-10-24 13:21:57 +0000162 * VALGRIND_DO_CLIENT_REQUEST_STMT(): a statement that invokes a Valgrind
163 * client request that does not return a value.
164
bart575ce8e2011-05-15 07:04:03 +0000165 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
sewardj4b3a7422011-10-24 13:21:57 +0000166 * client request and whose value equals the client request result. Accepts
167 * both pointers and integers as arguments. Note that such calls are not
168 * necessarily pure functions -- they may have side effects.
bart575ce8e2011-05-15 07:04:03 +0000169 */
170
171#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, \
172 _zzq_request, _zzq_arg1, _zzq_arg2, \
173 _zzq_arg3, _zzq_arg4, _zzq_arg5) \
florian17dfe1a2011-10-22 15:04:05 +0000174 do { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default), \
bart575ce8e2011-05-15 07:04:03 +0000175 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
florian17dfe1a2011-10-22 15:04:05 +0000176 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
bart575ce8e2011-05-15 07:04:03 +0000177
sewardj4b3a7422011-10-24 13:21:57 +0000178#define VALGRIND_DO_CLIENT_REQUEST_STMT(_zzq_request, _zzq_arg1, \
179 _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
180 do { (void) VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
181 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
182 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
183
sewardj0ec07f32006-01-12 12:32:32 +0000184#if defined(NVALGRIND)
njn26aba4d2005-05-16 13:31:23 +0000185
186/* Define NVALGRIND to completely remove the Valgrind magic sequence
sewardj0ec07f32006-01-12 12:32:32 +0000187 from the compiled code (analogous to NDEBUG's effects on
188 assert()) */
bart575ce8e2011-05-15 07:04:03 +0000189#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
190 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000191 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000192 (_zzq_default)
njn26aba4d2005-05-16 13:31:23 +0000193
sewardj0ec07f32006-01-12 12:32:32 +0000194#else /* ! NVALGRIND */
nethercotee90c6832004-10-18 18:07:49 +0000195
sewardj0ec07f32006-01-12 12:32:32 +0000196/* The following defines the magic code sequences which the JITter
197 spots and handles magically. Don't look too closely at them as
198 they will rot your brain.
199
200 The assembly code sequences for all architectures is in this one
201 file. This is because this file must be stand-alone, and we don't
202 want to have multiple files.
203
204 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
205 value gets put in the return slot, so that everything works when
206 this is executed not under Valgrind. Args are passed in a memory
207 block, and so there's no intrinsic limit to the number that could
sewardj9af10a12006-02-01 14:59:42 +0000208 be passed, but it's currently five.
nethercotee90c6832004-10-18 18:07:49 +0000209
nethercote54265442004-10-26 12:56:58 +0000210 The macro args are:
211 _zzq_rlval result lvalue
212 _zzq_default default value (result returned when running on real CPU)
213 _zzq_request request code
sewardj9af10a12006-02-01 14:59:42 +0000214 _zzq_arg1..5 request params
nethercote54265442004-10-26 12:56:58 +0000215
sewardj0ec07f32006-01-12 12:32:32 +0000216 The other two macros are used to support function wrapping, and are
sewardjd68ac3e2006-01-20 14:31:57 +0000217 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
218 guest's NRADDR pseudo-register and whatever other information is
219 needed to safely run the call original from the wrapper: on
220 ppc64-linux, the R2 value at the divert point is also needed. This
221 information is abstracted into a user-visible type, OrigFn.
222
223 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
224 guest, but guarantees that the branch instruction will not be
225 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
226 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
227 complete inline asm, since it needs to be combined with more magic
228 inline asm stuff to be useful.
nethercotee90c6832004-10-18 18:07:49 +0000229*/
230
njnf76d27a2009-05-28 01:53:07 +0000231/* ------------------------- x86-{linux,darwin} ---------------- */
sewardjde4a4ab2005-03-23 13:10:32 +0000232
sewardj520a03a2010-10-07 10:46:15 +0000233#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
sewardj60227842010-10-07 10:00:56 +0000234 || (defined(PLAT_x86_win32) && defined(__GNUC__))
sewardjc8858442006-01-20 15:17:20 +0000235
236typedef
237 struct {
238 unsigned int nraddr; /* where's the code? */
239 }
240 OrigFn;
241
sewardj0ec07f32006-01-12 12:32:32 +0000242#define __SPECIAL_INSTRUCTION_PREAMBLE \
243 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000244 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000245
bart575ce8e2011-05-15 07:04:03 +0000246#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
247 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000248 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000249 __extension__ \
250 ({volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000251 volatile unsigned int _zzq_result; \
252 _zzq_args[0] = (unsigned int)(_zzq_request); \
253 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
254 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
255 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
256 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000257 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000258 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
259 /* %EDX = client_request ( %EAX ) */ \
260 "xchgl %%ebx,%%ebx" \
261 : "=d" (_zzq_result) \
262 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
263 : "cc", "memory" \
264 ); \
bart575ce8e2011-05-15 07:04:03 +0000265 _zzq_result; \
266 })
sewardj2c48c7b2005-11-29 13:05:56 +0000267
sewardjc8858442006-01-20 15:17:20 +0000268#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
269 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
270 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000271 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
272 /* %EAX = guest_NRADDR */ \
273 "xchgl %%ecx,%%ecx" \
274 : "=a" (__addr) \
275 : \
276 : "cc", "memory" \
277 ); \
sewardjc8858442006-01-20 15:17:20 +0000278 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000279 }
sewardj0ec07f32006-01-12 12:32:32 +0000280
281#define VALGRIND_CALL_NOREDIR_EAX \
282 __SPECIAL_INSTRUCTION_PREAMBLE \
283 /* call-noredir *%EAX */ \
284 "xchgl %%edx,%%edx\n\t"
florianbb913cd2012-08-28 16:50:39 +0000285
286#define VALGRIND_VEX_INJECT_IR() \
287 do { \
288 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
289 "xchgl %%edi,%%edi\n\t" \
290 : : : "cc", "memory" \
291 ); \
292 } while (0)
293
sewardj60227842010-10-07 10:00:56 +0000294#endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__) */
bart7f489812010-08-27 10:05:27 +0000295
296/* ------------------------- x86-Win32 ------------------------- */
297
298#if defined(PLAT_x86_win32) && !defined(__GNUC__)
299
300typedef
301 struct {
302 unsigned int nraddr; /* where's the code? */
303 }
304 OrigFn;
305
306#if defined(_MSC_VER)
307
308#define __SPECIAL_INSTRUCTION_PREAMBLE \
309 __asm rol edi, 3 __asm rol edi, 13 \
310 __asm rol edi, 29 __asm rol edi, 19
311
bart575ce8e2011-05-15 07:04:03 +0000312#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
313 _zzq_default, _zzq_request, \
bart7f489812010-08-27 10:05:27 +0000314 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000315 valgrind_do_client_request_expr((uintptr_t)(_zzq_default), \
316 (uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1), \
317 (uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3), \
318 (uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5))
319
320static __inline uintptr_t
321valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request,
322 uintptr_t _zzq_arg1, uintptr_t _zzq_arg2,
323 uintptr_t _zzq_arg3, uintptr_t _zzq_arg4,
324 uintptr_t _zzq_arg5)
325{
326 volatile uintptr_t _zzq_args[6];
327 volatile unsigned int _zzq_result;
328 _zzq_args[0] = (uintptr_t)(_zzq_request);
329 _zzq_args[1] = (uintptr_t)(_zzq_arg1);
330 _zzq_args[2] = (uintptr_t)(_zzq_arg2);
331 _zzq_args[3] = (uintptr_t)(_zzq_arg3);
332 _zzq_args[4] = (uintptr_t)(_zzq_arg4);
333 _zzq_args[5] = (uintptr_t)(_zzq_arg5);
334 __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default
335 __SPECIAL_INSTRUCTION_PREAMBLE
336 /* %EDX = client_request ( %EAX ) */
337 __asm xchg ebx,ebx
338 __asm mov _zzq_result, edx
339 }
340 return _zzq_result;
341}
bart7f489812010-08-27 10:05:27 +0000342
343#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
344 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
345 volatile unsigned int __addr; \
346 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
347 /* %EAX = guest_NRADDR */ \
348 __asm xchg ecx,ecx \
349 __asm mov __addr, eax \
350 } \
351 _zzq_orig->nraddr = __addr; \
352 }
353
354#define VALGRIND_CALL_NOREDIR_EAX ERROR
355
florianbb913cd2012-08-28 16:50:39 +0000356#define VALGRIND_VEX_INJECT_IR() \
357 do { \
358 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
359 __asm xchg edi,edi \
360 } \
361 } while (0)
362
bart7f489812010-08-27 10:05:27 +0000363#else
364#error Unsupported compiler.
365#endif
366
367#endif /* PLAT_x86_win32 */
sewardj0ec07f32006-01-12 12:32:32 +0000368
njnf76d27a2009-05-28 01:53:07 +0000369/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000370
njnf76d27a2009-05-28 01:53:07 +0000371#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardjc8858442006-01-20 15:17:20 +0000372
373typedef
374 struct {
375 unsigned long long int nraddr; /* where's the code? */
376 }
377 OrigFn;
378
sewardj0ec07f32006-01-12 12:32:32 +0000379#define __SPECIAL_INSTRUCTION_PREAMBLE \
380 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000381 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000382
bart575ce8e2011-05-15 07:04:03 +0000383#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
384 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000385 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000386 __extension__ \
387 ({ volatile unsigned long long int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000388 volatile unsigned long long int _zzq_result; \
389 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
390 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
391 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
392 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
393 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000394 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000395 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
396 /* %RDX = client_request ( %RAX ) */ \
397 "xchgq %%rbx,%%rbx" \
398 : "=d" (_zzq_result) \
399 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
400 : "cc", "memory" \
401 ); \
bart575ce8e2011-05-15 07:04:03 +0000402 _zzq_result; \
403 })
sewardj0ec07f32006-01-12 12:32:32 +0000404
sewardjc8858442006-01-20 15:17:20 +0000405#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
406 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
407 volatile unsigned long long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000408 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
409 /* %RAX = guest_NRADDR */ \
410 "xchgq %%rcx,%%rcx" \
411 : "=a" (__addr) \
412 : \
413 : "cc", "memory" \
414 ); \
sewardjc8858442006-01-20 15:17:20 +0000415 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000416 }
417
418#define VALGRIND_CALL_NOREDIR_RAX \
419 __SPECIAL_INSTRUCTION_PREAMBLE \
420 /* call-noredir *%RAX */ \
421 "xchgq %%rdx,%%rdx\n\t"
florianbb913cd2012-08-28 16:50:39 +0000422
423#define VALGRIND_VEX_INJECT_IR() \
424 do { \
425 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
426 "xchgq %%rdi,%%rdi\n\t" \
427 : : : "cc", "memory" \
428 ); \
429 } while (0)
430
njnf76d27a2009-05-28 01:53:07 +0000431#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +0000432
sewardjf5c1a7f2006-10-17 01:32:48 +0000433/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000434
sewardjf5c1a7f2006-10-17 01:32:48 +0000435#if defined(PLAT_ppc32_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000436
437typedef
438 struct {
sewardjc8858442006-01-20 15:17:20 +0000439 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000440 }
441 OrigFn;
442
sewardj0ec07f32006-01-12 12:32:32 +0000443#define __SPECIAL_INSTRUCTION_PREAMBLE \
444 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000445 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000446
bart575ce8e2011-05-15 07:04:03 +0000447#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
448 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000449 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000450 \
bart575ce8e2011-05-15 07:04:03 +0000451 __extension__ \
452 ({ unsigned int _zzq_args[6]; \
sewardj1c5bcb12006-12-08 21:29:46 +0000453 unsigned int _zzq_result; \
454 unsigned int* _zzq_ptr; \
sewardj0ec07f32006-01-12 12:32:32 +0000455 _zzq_args[0] = (unsigned int)(_zzq_request); \
456 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
457 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
458 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
459 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000460 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000461 _zzq_ptr = _zzq_args; \
sewardj1c5bcb12006-12-08 21:29:46 +0000462 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
463 "mr 4,%2\n\t" /*ptr*/ \
464 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj0ec07f32006-01-12 12:32:32 +0000465 /* %R3 = client_request ( %R4 ) */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000466 "or 1,1,1\n\t" \
467 "mr %0,3" /*result*/ \
468 : "=b" (_zzq_result) \
469 : "b" (_zzq_default), "b" (_zzq_ptr) \
470 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000471 _zzq_result; \
472 })
sewardj0ec07f32006-01-12 12:32:32 +0000473
sewardjd68ac3e2006-01-20 14:31:57 +0000474#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
475 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj1c5bcb12006-12-08 21:29:46 +0000476 unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000477 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
478 /* %R3 = guest_NRADDR */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000479 "or 2,2,2\n\t" \
480 "mr %0,3" \
481 : "=b" (__addr) \
sewardj0ec07f32006-01-12 12:32:32 +0000482 : \
sewardj1c5bcb12006-12-08 21:29:46 +0000483 : "cc", "memory", "r3" \
sewardj0ec07f32006-01-12 12:32:32 +0000484 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000485 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000486 }
487
488#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
489 __SPECIAL_INSTRUCTION_PREAMBLE \
490 /* branch-and-link-to-noredir *%R11 */ \
491 "or 3,3,3\n\t"
sewardjf5c1a7f2006-10-17 01:32:48 +0000492#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000493
sewardjf5c1a7f2006-10-17 01:32:48 +0000494/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000495
sewardjf5c1a7f2006-10-17 01:32:48 +0000496#if defined(PLAT_ppc64_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000497
498typedef
499 struct {
500 unsigned long long int nraddr; /* where's the code? */
501 unsigned long long int r2; /* what tocptr do we need? */
502 }
503 OrigFn;
504
sewardj1a85f4f2006-01-12 21:15:35 +0000505#define __SPECIAL_INSTRUCTION_PREAMBLE \
506 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
507 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
508
bart575ce8e2011-05-15 07:04:03 +0000509#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
510 _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000511 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000512 \
bart575ce8e2011-05-15 07:04:03 +0000513 __extension__ \
514 ({ unsigned long long int _zzq_args[6]; \
sewardj8258a3a2011-10-05 07:39:07 +0000515 unsigned long long int _zzq_result; \
516 unsigned long long int* _zzq_ptr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000517 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
518 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
519 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
520 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
521 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000522 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000523 _zzq_ptr = _zzq_args; \
sewardj8258a3a2011-10-05 07:39:07 +0000524 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
525 "mr 4,%2\n\t" /*ptr*/ \
526 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj1a85f4f2006-01-12 21:15:35 +0000527 /* %R3 = client_request ( %R4 ) */ \
sewardj8258a3a2011-10-05 07:39:07 +0000528 "or 1,1,1\n\t" \
529 "mr %0,3" /*result*/ \
530 : "=b" (_zzq_result) \
531 : "b" (_zzq_default), "b" (_zzq_ptr) \
532 : "cc", "memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000533 _zzq_result; \
534 })
sewardj1a85f4f2006-01-12 21:15:35 +0000535
sewardjd68ac3e2006-01-20 14:31:57 +0000536#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
537 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj8258a3a2011-10-05 07:39:07 +0000538 unsigned long long int __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000539 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
540 /* %R3 = guest_NRADDR */ \
sewardj8258a3a2011-10-05 07:39:07 +0000541 "or 2,2,2\n\t" \
542 "mr %0,3" \
543 : "=b" (__addr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000544 : \
sewardj8258a3a2011-10-05 07:39:07 +0000545 : "cc", "memory", "r3" \
sewardj1a85f4f2006-01-12 21:15:35 +0000546 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000547 _zzq_orig->nraddr = __addr; \
548 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
549 /* %R3 = guest_NRADDR_GPR2 */ \
sewardj8258a3a2011-10-05 07:39:07 +0000550 "or 4,4,4\n\t" \
551 "mr %0,3" \
552 : "=b" (__addr) \
sewardjd68ac3e2006-01-20 14:31:57 +0000553 : \
sewardj8258a3a2011-10-05 07:39:07 +0000554 : "cc", "memory", "r3" \
sewardjd68ac3e2006-01-20 14:31:57 +0000555 ); \
556 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000557 }
558
559#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
560 __SPECIAL_INSTRUCTION_PREAMBLE \
561 /* branch-and-link-to-noredir *%R11 */ \
562 "or 3,3,3\n\t"
563
florianbb913cd2012-08-28 16:50:39 +0000564#define VALGRIND_VEX_INJECT_IR() \
565 do { \
566 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
567 "or 5,5,5\n\t" \
568 ); \
569 } while (0)
570
sewardjf5c1a7f2006-10-17 01:32:48 +0000571#endif /* PLAT_ppc64_linux */
cerion85665ca2005-06-20 15:51:07 +0000572
sewardj59570ff2010-01-01 11:59:33 +0000573/* ------------------------- arm-linux ------------------------- */
574
575#if defined(PLAT_arm_linux)
576
577typedef
578 struct {
579 unsigned int nraddr; /* where's the code? */
580 }
581 OrigFn;
582
583#define __SPECIAL_INSTRUCTION_PREAMBLE \
584 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
585 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
586
bart575ce8e2011-05-15 07:04:03 +0000587#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
588 _zzq_default, _zzq_request, \
sewardj59570ff2010-01-01 11:59:33 +0000589 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
590 \
bart575ce8e2011-05-15 07:04:03 +0000591 __extension__ \
592 ({volatile unsigned int _zzq_args[6]; \
sewardj59570ff2010-01-01 11:59:33 +0000593 volatile unsigned int _zzq_result; \
594 _zzq_args[0] = (unsigned int)(_zzq_request); \
595 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
596 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
597 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
598 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
599 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
600 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
601 "mov r4, %2\n\t" /*ptr*/ \
602 __SPECIAL_INSTRUCTION_PREAMBLE \
603 /* R3 = client_request ( R4 ) */ \
604 "orr r10, r10, r10\n\t" \
605 "mov %0, r3" /*result*/ \
606 : "=r" (_zzq_result) \
607 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
608 : "cc","memory", "r3", "r4"); \
bart575ce8e2011-05-15 07:04:03 +0000609 _zzq_result; \
610 })
sewardj59570ff2010-01-01 11:59:33 +0000611
612#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
613 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
614 unsigned int __addr; \
615 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
616 /* R3 = guest_NRADDR */ \
617 "orr r11, r11, r11\n\t" \
618 "mov %0, r3" \
619 : "=r" (__addr) \
620 : \
621 : "cc", "memory", "r3" \
622 ); \
623 _zzq_orig->nraddr = __addr; \
624 }
625
626#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
627 __SPECIAL_INSTRUCTION_PREAMBLE \
628 /* branch-and-link-to-noredir *%R4 */ \
629 "orr r12, r12, r12\n\t"
630
florianbb913cd2012-08-28 16:50:39 +0000631#define VALGRIND_VEX_INJECT_IR() \
632 do { \
633 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
634 "orr r13, r13, r13\n\t" \
635 : : : "cc", "memory" \
636 ); \
637 } while (0)
638
sewardj59570ff2010-01-01 11:59:33 +0000639#endif /* PLAT_arm_linux */
640
sewardjb5b87402011-03-07 16:05:35 +0000641/* ------------------------ s390x-linux ------------------------ */
642
643#if defined(PLAT_s390x_linux)
644
645typedef
646 struct {
647 unsigned long long int nraddr; /* where's the code? */
648 }
649 OrigFn;
650
651/* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific
652 * code. This detection is implemented in platform specific toIR.c
653 * (e.g. VEX/priv/guest_s390_decoder.c).
654 */
655#define __SPECIAL_INSTRUCTION_PREAMBLE \
656 "lr 15,15\n\t" \
657 "lr 1,1\n\t" \
658 "lr 2,2\n\t" \
659 "lr 3,3\n\t"
660
661#define __CLIENT_REQUEST_CODE "lr 2,2\n\t"
662#define __GET_NR_CONTEXT_CODE "lr 3,3\n\t"
663#define __CALL_NO_REDIR_CODE "lr 4,4\n\t"
florianbb913cd2012-08-28 16:50:39 +0000664#define __VEX_INJECT_IR_CODE "lr 5,5\n\t"
sewardjb5b87402011-03-07 16:05:35 +0000665
bart575ce8e2011-05-15 07:04:03 +0000666#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
667 _zzq_default, _zzq_request, \
sewardjb5b87402011-03-07 16:05:35 +0000668 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bart575ce8e2011-05-15 07:04:03 +0000669 __extension__ \
670 ({volatile unsigned long long int _zzq_args[6]; \
sewardjb5b87402011-03-07 16:05:35 +0000671 volatile unsigned long long int _zzq_result; \
672 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
673 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
674 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
675 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
676 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
677 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
678 __asm__ volatile(/* r2 = args */ \
679 "lgr 2,%1\n\t" \
680 /* r3 = default */ \
681 "lgr 3,%2\n\t" \
682 __SPECIAL_INSTRUCTION_PREAMBLE \
683 __CLIENT_REQUEST_CODE \
684 /* results = r3 */ \
685 "lgr %0, 3\n\t" \
686 : "=d" (_zzq_result) \
687 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
688 : "cc", "2", "3", "memory" \
689 ); \
bart575ce8e2011-05-15 07:04:03 +0000690 _zzq_result; \
691 })
sewardjb5b87402011-03-07 16:05:35 +0000692
693#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
694 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
695 volatile unsigned long long int __addr; \
696 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
697 __GET_NR_CONTEXT_CODE \
698 "lgr %0, 3\n\t" \
699 : "=a" (__addr) \
700 : \
701 : "cc", "3", "memory" \
702 ); \
703 _zzq_orig->nraddr = __addr; \
704 }
705
706#define VALGRIND_CALL_NOREDIR_R1 \
707 __SPECIAL_INSTRUCTION_PREAMBLE \
708 __CALL_NO_REDIR_CODE
709
florianbb913cd2012-08-28 16:50:39 +0000710#define VALGRIND_VEX_INJECT_IR() \
711 do { \
712 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
713 __VEX_INJECT_IR_CODE); \
714 } while (0)
715
sewardjb5b87402011-03-07 16:05:35 +0000716#endif /* PLAT_s390x_linux */
717
sewardj5db15402012-06-07 09:13:21 +0000718/* ------------------------- mips32-linux ---------------- */
719
720#if defined(PLAT_mips32_linux)
721
722typedef
723 struct {
724 unsigned int nraddr; /* where's the code? */
725 }
726 OrigFn;
727
728/* .word 0x342
729 * .word 0x742
730 * .word 0xC2
731 * .word 0x4C2*/
732#define __SPECIAL_INSTRUCTION_PREAMBLE \
733 "srl $0, $0, 13\n\t" \
734 "srl $0, $0, 29\n\t" \
735 "srl $0, $0, 3\n\t" \
736 "srl $0, $0, 19\n\t"
737
738#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
739 _zzq_default, _zzq_request, \
740 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
741 __extension__ \
742 ({ volatile unsigned int _zzq_args[6]; \
743 volatile unsigned int _zzq_result; \
744 _zzq_args[0] = (unsigned int)(_zzq_request); \
745 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
746 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
747 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
748 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
749 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
750 __asm__ volatile("move $11, %1\n\t" /*default*/ \
751 "move $12, %2\n\t" /*ptr*/ \
752 __SPECIAL_INSTRUCTION_PREAMBLE \
753 /* T3 = client_request ( T4 ) */ \
754 "or $13, $13, $13\n\t" \
755 "move %0, $11\n\t" /*result*/ \
756 : "=r" (_zzq_result) \
757 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
758 : "cc","memory", "t3", "t4"); \
759 _zzq_result; \
760 })
761
762#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
763 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
764 volatile unsigned int __addr; \
765 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
766 /* %t9 = guest_NRADDR */ \
767 "or $14, $14, $14\n\t" \
768 "move %0, $11" /*result*/ \
769 : "=r" (__addr) \
770 : \
771 : "cc", "memory" , "t3" \
772 ); \
773 _zzq_orig->nraddr = __addr; \
774 }
775
776#define VALGRIND_CALL_NOREDIR_T9 \
777 __SPECIAL_INSTRUCTION_PREAMBLE \
778 /* call-noredir *%t9 */ \
florianbb913cd2012-08-28 16:50:39 +0000779 "or $15, $15, $15\n\t"
780
781#define VALGRIND_VEX_INJECT_IR() \
782 do { \
783 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
784 "or $11, $11, $11\n\t" \
785 ); \
786 } while (0)
787
788
sewardj5db15402012-06-07 09:13:21 +0000789#endif /* PLAT_mips32_linux */
790
sewardjf5c1a7f2006-10-17 01:32:48 +0000791/* Insert assembly code for other platforms here... */
njn26aba4d2005-05-16 13:31:23 +0000792
sewardj37091fb2002-11-16 11:06:50 +0000793#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +0000794
nethercote69d9c462004-10-26 13:00:12 +0000795
njn30d76c62005-06-18 15:07:39 +0000796/* ------------------------------------------------------------------ */
sewardjf5c1a7f2006-10-17 01:32:48 +0000797/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
sewardj0ec07f32006-01-12 12:32:32 +0000798/* ugly. It's the least-worst tradeoff I can think of. */
799/* ------------------------------------------------------------------ */
800
801/* This section defines magic (a.k.a appalling-hack) macros for doing
802 guaranteed-no-redirection macros, so as to get from function
803 wrappers to the functions they are wrapping. The whole point is to
804 construct standard call sequences, but to do the call itself with a
805 special no-redirect call pseudo-instruction that the JIT
806 understands and handles specially. This section is long and
807 repetitious, and I can't see a way to make it shorter.
808
809 The naming scheme is as follows:
810
811 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
812
813 'W' stands for "word" and 'v' for "void". Hence there are
814 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
815 and for each, the possibility of returning a word-typed result, or
816 no result.
817*/
818
819/* Use these to write the name of your wrapper. NOTE: duplicates
sewardj85cf9002011-08-16 09:54:00 +0000820 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. NOTE also: inserts
821 the default behaviour equivalance class tag "0000" into the name.
822 See pub_tool_redir.h for details -- normally you don't need to
823 think about this, though. */
sewardj0ec07f32006-01-12 12:32:32 +0000824
njn5f5ef2a2009-05-11 08:01:09 +0000825/* Use an extra level of macroisation so as to ensure the soname/fnname
826 args are fully macro-expanded before pasting them together. */
827#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
828
sewardj0ec07f32006-01-12 12:32:32 +0000829#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +0000830 VG_CONCAT4(_vgw00000ZU_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000831
832#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
sewardj96044842011-08-18 13:09:55 +0000833 VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000834
sewardjd68ac3e2006-01-20 14:31:57 +0000835/* Use this macro from within a wrapper function to collect the
836 context (address and possibly other info) of the original function.
837 Once you have that you can then use it in one of the CALL_FN_
838 macros. The type of the argument _lval is OrigFn. */
839#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +0000840
sewardj573f8bc2012-06-05 07:12:15 +0000841/* Also provide end-user facilities for function replacement, rather
842 than wrapping. A replacement function differs from a wrapper in
843 that it has no way to get hold of the original function being
844 called, and hence no way to call onwards to it. In a replacement
845 function, VALGRIND_GET_ORIG_FN always returns zero. */
846
847#define I_REPLACE_SONAME_FNNAME_ZU(soname,fnname) \
848 VG_CONCAT4(_vgr00000ZU_,soname,_,fnname)
849
850#define I_REPLACE_SONAME_FNNAME_ZZ(soname,fnname) \
851 VG_CONCAT4(_vgr00000ZZ_,soname,_,fnname)
852
sewardj0ec07f32006-01-12 12:32:32 +0000853/* Derivatives of the main macros below, for calling functions
854 returning void. */
855
856#define CALL_FN_v_v(fnptr) \
857 do { volatile unsigned long _junk; \
858 CALL_FN_W_v(_junk,fnptr); } while (0)
859
860#define CALL_FN_v_W(fnptr, arg1) \
861 do { volatile unsigned long _junk; \
862 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
863
864#define CALL_FN_v_WW(fnptr, arg1,arg2) \
865 do { volatile unsigned long _junk; \
866 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
867
sewardj5ce4b152006-03-11 12:57:41 +0000868#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
869 do { volatile unsigned long _junk; \
870 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
871
njn2b5f0a92009-05-19 01:24:50 +0000872#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
873 do { volatile unsigned long _junk; \
874 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
875
876#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
877 do { volatile unsigned long _junk; \
878 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
879
880#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
881 do { volatile unsigned long _junk; \
882 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
883
884#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
885 do { volatile unsigned long _junk; \
886 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
887
njnf76d27a2009-05-28 01:53:07 +0000888/* ------------------------- x86-{linux,darwin} ---------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000889
njnf76d27a2009-05-28 01:53:07 +0000890#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
sewardj0ec07f32006-01-12 12:32:32 +0000891
892/* These regs are trashed by the hidden call. No need to mention eax
893 as gcc can already see that, plus causes gcc to bomb. */
894#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
895
tom4118e0f2012-08-02 09:23:45 +0000896/* Macros to save and align the stack before making a function
897 call and restore it afterwards as gcc may not keep the stack
898 pointer aligned if it doesn't realise calls are being made
899 to other functions. */
900
901#define VALGRIND_ALIGN_STACK \
902 "movl %%esp,%%edi\n\t" \
903 "andl $0xfffffff0,%%esp\n\t"
904#define VALGRIND_RESTORE_STACK \
905 "movl %%edi,%%esp\n\t"
906
sewardj0ec07f32006-01-12 12:32:32 +0000907/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
908 long) == 4. */
909
sewardj66226cc2006-01-20 15:46:46 +0000910#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +0000911 do { \
sewardj66226cc2006-01-20 15:46:46 +0000912 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000913 volatile unsigned long _argvec[1]; \
914 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000915 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000916 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +0000917 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +0000918 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
919 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +0000920 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +0000921 : /*out*/ "=a" (_res) \
922 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +0000923 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +0000924 ); \
925 lval = (__typeof__(lval)) _res; \
926 } while (0)
927
sewardj66226cc2006-01-20 15:46:46 +0000928#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +0000929 do { \
sewardj66226cc2006-01-20 15:46:46 +0000930 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000931 volatile unsigned long _argvec[2]; \
932 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000933 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000934 _argvec[1] = (unsigned long)(arg1); \
935 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +0000936 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +0000937 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000938 "pushl 4(%%eax)\n\t" \
939 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
940 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +0000941 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +0000942 : /*out*/ "=a" (_res) \
943 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +0000944 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +0000945 ); \
946 lval = (__typeof__(lval)) _res; \
947 } while (0)
948
sewardj66226cc2006-01-20 15:46:46 +0000949#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +0000950 do { \
sewardj66226cc2006-01-20 15:46:46 +0000951 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000952 volatile unsigned long _argvec[3]; \
953 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000954 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000955 _argvec[1] = (unsigned long)(arg1); \
956 _argvec[2] = (unsigned long)(arg2); \
957 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +0000958 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +0000959 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +0000960 "pushl 8(%%eax)\n\t" \
961 "pushl 4(%%eax)\n\t" \
962 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
963 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +0000964 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +0000965 : /*out*/ "=a" (_res) \
966 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +0000967 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +0000968 ); \
969 lval = (__typeof__(lval)) _res; \
970 } while (0)
971
sewardj9e8b07a2006-02-18 21:13:29 +0000972#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
973 do { \
974 volatile OrigFn _orig = (orig); \
975 volatile unsigned long _argvec[4]; \
976 volatile unsigned long _res; \
977 _argvec[0] = (unsigned long)_orig.nraddr; \
978 _argvec[1] = (unsigned long)(arg1); \
979 _argvec[2] = (unsigned long)(arg2); \
980 _argvec[3] = (unsigned long)(arg3); \
981 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +0000982 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +0000983 "subl $4, %%esp\n\t" \
sewardj9e8b07a2006-02-18 21:13:29 +0000984 "pushl 12(%%eax)\n\t" \
985 "pushl 8(%%eax)\n\t" \
986 "pushl 4(%%eax)\n\t" \
987 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
988 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +0000989 VALGRIND_RESTORE_STACK \
sewardj9e8b07a2006-02-18 21:13:29 +0000990 : /*out*/ "=a" (_res) \
991 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +0000992 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj9e8b07a2006-02-18 21:13:29 +0000993 ); \
994 lval = (__typeof__(lval)) _res; \
995 } while (0)
996
sewardj66226cc2006-01-20 15:46:46 +0000997#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
sewardj0ec07f32006-01-12 12:32:32 +0000998 do { \
sewardj66226cc2006-01-20 15:46:46 +0000999 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001000 volatile unsigned long _argvec[5]; \
1001 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001002 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001003 _argvec[1] = (unsigned long)(arg1); \
1004 _argvec[2] = (unsigned long)(arg2); \
1005 _argvec[3] = (unsigned long)(arg3); \
1006 _argvec[4] = (unsigned long)(arg4); \
1007 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001008 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001009 "pushl 16(%%eax)\n\t" \
1010 "pushl 12(%%eax)\n\t" \
1011 "pushl 8(%%eax)\n\t" \
1012 "pushl 4(%%eax)\n\t" \
1013 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1014 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001015 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001016 : /*out*/ "=a" (_res) \
1017 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001018 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001019 ); \
1020 lval = (__typeof__(lval)) _res; \
1021 } while (0)
1022
sewardj66226cc2006-01-20 15:46:46 +00001023#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +00001024 do { \
sewardj66226cc2006-01-20 15:46:46 +00001025 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001026 volatile unsigned long _argvec[6]; \
1027 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001028 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001029 _argvec[1] = (unsigned long)(arg1); \
1030 _argvec[2] = (unsigned long)(arg2); \
1031 _argvec[3] = (unsigned long)(arg3); \
1032 _argvec[4] = (unsigned long)(arg4); \
1033 _argvec[5] = (unsigned long)(arg5); \
1034 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001035 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001036 "subl $12, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001037 "pushl 20(%%eax)\n\t" \
1038 "pushl 16(%%eax)\n\t" \
1039 "pushl 12(%%eax)\n\t" \
1040 "pushl 8(%%eax)\n\t" \
1041 "pushl 4(%%eax)\n\t" \
1042 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1043 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001044 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001045 : /*out*/ "=a" (_res) \
1046 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001047 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001048 ); \
1049 lval = (__typeof__(lval)) _res; \
1050 } while (0)
1051
sewardj66226cc2006-01-20 15:46:46 +00001052#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +00001053 do { \
sewardj66226cc2006-01-20 15:46:46 +00001054 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001055 volatile unsigned long _argvec[7]; \
1056 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001057 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001058 _argvec[1] = (unsigned long)(arg1); \
1059 _argvec[2] = (unsigned long)(arg2); \
1060 _argvec[3] = (unsigned long)(arg3); \
1061 _argvec[4] = (unsigned long)(arg4); \
1062 _argvec[5] = (unsigned long)(arg5); \
1063 _argvec[6] = (unsigned long)(arg6); \
1064 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001065 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001066 "subl $8, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001067 "pushl 24(%%eax)\n\t" \
1068 "pushl 20(%%eax)\n\t" \
1069 "pushl 16(%%eax)\n\t" \
1070 "pushl 12(%%eax)\n\t" \
1071 "pushl 8(%%eax)\n\t" \
1072 "pushl 4(%%eax)\n\t" \
1073 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1074 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001075 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001076 : /*out*/ "=a" (_res) \
1077 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001078 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001079 ); \
1080 lval = (__typeof__(lval)) _res; \
1081 } while (0)
1082
sewardj66226cc2006-01-20 15:46:46 +00001083#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1084 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +00001085 do { \
sewardj66226cc2006-01-20 15:46:46 +00001086 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001087 volatile unsigned long _argvec[8]; \
1088 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001089 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001090 _argvec[1] = (unsigned long)(arg1); \
1091 _argvec[2] = (unsigned long)(arg2); \
1092 _argvec[3] = (unsigned long)(arg3); \
1093 _argvec[4] = (unsigned long)(arg4); \
1094 _argvec[5] = (unsigned long)(arg5); \
1095 _argvec[6] = (unsigned long)(arg6); \
1096 _argvec[7] = (unsigned long)(arg7); \
1097 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001098 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001099 "subl $4, %%esp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001100 "pushl 28(%%eax)\n\t" \
1101 "pushl 24(%%eax)\n\t" \
1102 "pushl 20(%%eax)\n\t" \
1103 "pushl 16(%%eax)\n\t" \
1104 "pushl 12(%%eax)\n\t" \
1105 "pushl 8(%%eax)\n\t" \
1106 "pushl 4(%%eax)\n\t" \
1107 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1108 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001109 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001110 : /*out*/ "=a" (_res) \
1111 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001112 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001113 ); \
1114 lval = (__typeof__(lval)) _res; \
1115 } while (0)
1116
sewardj66226cc2006-01-20 15:46:46 +00001117#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1118 arg7,arg8) \
sewardj0ec07f32006-01-12 12:32:32 +00001119 do { \
sewardj66226cc2006-01-20 15:46:46 +00001120 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001121 volatile unsigned long _argvec[9]; \
1122 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001123 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001124 _argvec[1] = (unsigned long)(arg1); \
1125 _argvec[2] = (unsigned long)(arg2); \
1126 _argvec[3] = (unsigned long)(arg3); \
1127 _argvec[4] = (unsigned long)(arg4); \
1128 _argvec[5] = (unsigned long)(arg5); \
1129 _argvec[6] = (unsigned long)(arg6); \
1130 _argvec[7] = (unsigned long)(arg7); \
1131 _argvec[8] = (unsigned long)(arg8); \
1132 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001133 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001134 "pushl 32(%%eax)\n\t" \
1135 "pushl 28(%%eax)\n\t" \
1136 "pushl 24(%%eax)\n\t" \
1137 "pushl 20(%%eax)\n\t" \
1138 "pushl 16(%%eax)\n\t" \
1139 "pushl 12(%%eax)\n\t" \
1140 "pushl 8(%%eax)\n\t" \
1141 "pushl 4(%%eax)\n\t" \
1142 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1143 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001144 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001145 : /*out*/ "=a" (_res) \
1146 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001147 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001148 ); \
1149 lval = (__typeof__(lval)) _res; \
1150 } while (0)
1151
sewardj45fa5b02006-03-09 19:06:23 +00001152#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1153 arg7,arg8,arg9) \
1154 do { \
1155 volatile OrigFn _orig = (orig); \
1156 volatile unsigned long _argvec[10]; \
1157 volatile unsigned long _res; \
1158 _argvec[0] = (unsigned long)_orig.nraddr; \
1159 _argvec[1] = (unsigned long)(arg1); \
1160 _argvec[2] = (unsigned long)(arg2); \
1161 _argvec[3] = (unsigned long)(arg3); \
1162 _argvec[4] = (unsigned long)(arg4); \
1163 _argvec[5] = (unsigned long)(arg5); \
1164 _argvec[6] = (unsigned long)(arg6); \
1165 _argvec[7] = (unsigned long)(arg7); \
1166 _argvec[8] = (unsigned long)(arg8); \
1167 _argvec[9] = (unsigned long)(arg9); \
1168 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001169 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001170 "subl $12, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001171 "pushl 36(%%eax)\n\t" \
1172 "pushl 32(%%eax)\n\t" \
1173 "pushl 28(%%eax)\n\t" \
1174 "pushl 24(%%eax)\n\t" \
1175 "pushl 20(%%eax)\n\t" \
1176 "pushl 16(%%eax)\n\t" \
1177 "pushl 12(%%eax)\n\t" \
1178 "pushl 8(%%eax)\n\t" \
1179 "pushl 4(%%eax)\n\t" \
1180 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1181 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001182 VALGRIND_RESTORE_STACK \
sewardj45fa5b02006-03-09 19:06:23 +00001183 : /*out*/ "=a" (_res) \
1184 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001185 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj45fa5b02006-03-09 19:06:23 +00001186 ); \
1187 lval = (__typeof__(lval)) _res; \
1188 } while (0)
1189
1190#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1191 arg7,arg8,arg9,arg10) \
1192 do { \
1193 volatile OrigFn _orig = (orig); \
1194 volatile unsigned long _argvec[11]; \
1195 volatile unsigned long _res; \
1196 _argvec[0] = (unsigned long)_orig.nraddr; \
1197 _argvec[1] = (unsigned long)(arg1); \
1198 _argvec[2] = (unsigned long)(arg2); \
1199 _argvec[3] = (unsigned long)(arg3); \
1200 _argvec[4] = (unsigned long)(arg4); \
1201 _argvec[5] = (unsigned long)(arg5); \
1202 _argvec[6] = (unsigned long)(arg6); \
1203 _argvec[7] = (unsigned long)(arg7); \
1204 _argvec[8] = (unsigned long)(arg8); \
1205 _argvec[9] = (unsigned long)(arg9); \
1206 _argvec[10] = (unsigned long)(arg10); \
1207 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001208 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001209 "subl $8, %%esp\n\t" \
sewardj45fa5b02006-03-09 19:06:23 +00001210 "pushl 40(%%eax)\n\t" \
1211 "pushl 36(%%eax)\n\t" \
1212 "pushl 32(%%eax)\n\t" \
1213 "pushl 28(%%eax)\n\t" \
1214 "pushl 24(%%eax)\n\t" \
1215 "pushl 20(%%eax)\n\t" \
1216 "pushl 16(%%eax)\n\t" \
1217 "pushl 12(%%eax)\n\t" \
1218 "pushl 8(%%eax)\n\t" \
1219 "pushl 4(%%eax)\n\t" \
1220 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1221 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001222 VALGRIND_RESTORE_STACK \
sewardj45fa5b02006-03-09 19:06:23 +00001223 : /*out*/ "=a" (_res) \
1224 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001225 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj45fa5b02006-03-09 19:06:23 +00001226 ); \
1227 lval = (__typeof__(lval)) _res; \
1228 } while (0)
1229
sewardj5ce4b152006-03-11 12:57:41 +00001230#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1231 arg6,arg7,arg8,arg9,arg10, \
1232 arg11) \
1233 do { \
1234 volatile OrigFn _orig = (orig); \
1235 volatile unsigned long _argvec[12]; \
1236 volatile unsigned long _res; \
1237 _argvec[0] = (unsigned long)_orig.nraddr; \
1238 _argvec[1] = (unsigned long)(arg1); \
1239 _argvec[2] = (unsigned long)(arg2); \
1240 _argvec[3] = (unsigned long)(arg3); \
1241 _argvec[4] = (unsigned long)(arg4); \
1242 _argvec[5] = (unsigned long)(arg5); \
1243 _argvec[6] = (unsigned long)(arg6); \
1244 _argvec[7] = (unsigned long)(arg7); \
1245 _argvec[8] = (unsigned long)(arg8); \
1246 _argvec[9] = (unsigned long)(arg9); \
1247 _argvec[10] = (unsigned long)(arg10); \
1248 _argvec[11] = (unsigned long)(arg11); \
1249 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001250 VALGRIND_ALIGN_STACK \
sewardj87a287b2010-10-20 15:58:09 +00001251 "subl $4, %%esp\n\t" \
sewardj5ce4b152006-03-11 12:57:41 +00001252 "pushl 44(%%eax)\n\t" \
1253 "pushl 40(%%eax)\n\t" \
1254 "pushl 36(%%eax)\n\t" \
1255 "pushl 32(%%eax)\n\t" \
1256 "pushl 28(%%eax)\n\t" \
1257 "pushl 24(%%eax)\n\t" \
1258 "pushl 20(%%eax)\n\t" \
1259 "pushl 16(%%eax)\n\t" \
1260 "pushl 12(%%eax)\n\t" \
1261 "pushl 8(%%eax)\n\t" \
1262 "pushl 4(%%eax)\n\t" \
1263 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1264 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001265 VALGRIND_RESTORE_STACK \
sewardj5ce4b152006-03-11 12:57:41 +00001266 : /*out*/ "=a" (_res) \
1267 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001268 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj5ce4b152006-03-11 12:57:41 +00001269 ); \
1270 lval = (__typeof__(lval)) _res; \
1271 } while (0)
1272
sewardj66226cc2006-01-20 15:46:46 +00001273#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1274 arg6,arg7,arg8,arg9,arg10, \
1275 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +00001276 do { \
sewardj66226cc2006-01-20 15:46:46 +00001277 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001278 volatile unsigned long _argvec[13]; \
1279 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001280 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001281 _argvec[1] = (unsigned long)(arg1); \
1282 _argvec[2] = (unsigned long)(arg2); \
1283 _argvec[3] = (unsigned long)(arg3); \
1284 _argvec[4] = (unsigned long)(arg4); \
1285 _argvec[5] = (unsigned long)(arg5); \
1286 _argvec[6] = (unsigned long)(arg6); \
1287 _argvec[7] = (unsigned long)(arg7); \
1288 _argvec[8] = (unsigned long)(arg8); \
1289 _argvec[9] = (unsigned long)(arg9); \
1290 _argvec[10] = (unsigned long)(arg10); \
1291 _argvec[11] = (unsigned long)(arg11); \
1292 _argvec[12] = (unsigned long)(arg12); \
1293 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001294 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001295 "pushl 48(%%eax)\n\t" \
1296 "pushl 44(%%eax)\n\t" \
1297 "pushl 40(%%eax)\n\t" \
1298 "pushl 36(%%eax)\n\t" \
1299 "pushl 32(%%eax)\n\t" \
1300 "pushl 28(%%eax)\n\t" \
1301 "pushl 24(%%eax)\n\t" \
1302 "pushl 20(%%eax)\n\t" \
1303 "pushl 16(%%eax)\n\t" \
1304 "pushl 12(%%eax)\n\t" \
1305 "pushl 8(%%eax)\n\t" \
1306 "pushl 4(%%eax)\n\t" \
1307 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1308 VALGRIND_CALL_NOREDIR_EAX \
tom4118e0f2012-08-02 09:23:45 +00001309 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001310 : /*out*/ "=a" (_res) \
1311 : /*in*/ "a" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001312 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
sewardj0ec07f32006-01-12 12:32:32 +00001313 ); \
1314 lval = (__typeof__(lval)) _res; \
1315 } while (0)
1316
njnf76d27a2009-05-28 01:53:07 +00001317#endif /* PLAT_x86_linux || PLAT_x86_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001318
njnf76d27a2009-05-28 01:53:07 +00001319/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001320
njnf76d27a2009-05-28 01:53:07 +00001321#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardj0ec07f32006-01-12 12:32:32 +00001322
1323/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1324
1325/* These regs are trashed by the hidden call. */
1326#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1327 "rdi", "r8", "r9", "r10", "r11"
1328
sewardjdfa55cf2010-10-06 22:07:06 +00001329/* This is all pretty complex. It's so as to make stack unwinding
1330 work reliably. See bug 243270. The basic problem is the sub and
1331 add of 128 of %rsp in all of the following macros. If gcc believes
1332 the CFA is in %rsp, then unwinding may fail, because what's at the
1333 CFA is not what gcc "expected" when it constructs the CFIs for the
1334 places where the macros are instantiated.
1335
1336 But we can't just add a CFI annotation to increase the CFA offset
1337 by 128, to match the sub of 128 from %rsp, because we don't know
1338 whether gcc has chosen %rsp as the CFA at that point, or whether it
1339 has chosen some other register (eg, %rbp). In the latter case,
1340 adding a CFI annotation to change the CFA offset is simply wrong.
1341
1342 So the solution is to get hold of the CFA using
sewardj8d1dc152010-10-08 17:43:26 +00001343 __builtin_dwarf_cfa(), put it in a known register, and add a
sewardjdfa55cf2010-10-06 22:07:06 +00001344 CFI annotation to say what the register is. We choose %rbp for
1345 this (perhaps perversely), because:
1346
1347 (1) %rbp is already subject to unwinding. If a new register was
1348 chosen then the unwinder would have to unwind it in all stack
1349 traces, which is expensive, and
1350
1351 (2) %rbp is already subject to precise exception updates in the
1352 JIT. If a new register was chosen, we'd have to have precise
1353 exceptions for it too, which reduces performance of the
1354 generated code.
1355
1356 However .. one extra complication. We can't just whack the result
sewardj8d1dc152010-10-08 17:43:26 +00001357 of __builtin_dwarf_cfa() into %rbp and then add %rbp to the
sewardjdfa55cf2010-10-06 22:07:06 +00001358 list of trashed registers at the end of the inline assembly
1359 fragments; gcc won't allow %rbp to appear in that list. Hence
1360 instead we need to stash %rbp in %r15 for the duration of the asm,
1361 and say that %r15 is trashed instead. gcc seems happy to go with
1362 that.
1363
1364 Oh .. and this all needs to be conditionalised so that it is
1365 unchanged from before this commit, when compiled with older gccs
sewardj8d1dc152010-10-08 17:43:26 +00001366 that don't support __builtin_dwarf_cfa. Furthermore, since
1367 this header file is freestanding, it has to be independent of
1368 config.h, and so the following conditionalisation cannot depend on
1369 configure time checks.
1370
1371 Although it's not clear from
1372 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)',
1373 this expression excludes Darwin.
1374 .cfi directives in Darwin assembly appear to be completely
1375 different and I haven't investigated how they work.
1376
1377 For even more entertainment value, note we have to use the
1378 completely undocumented __builtin_dwarf_cfa(), which appears to
1379 really compute the CFA, whereas __builtin_frame_address(0) claims
1380 to but actually doesn't. See
1381 https://bugs.kde.org/show_bug.cgi?id=243270#c47
sewardjdfa55cf2010-10-06 22:07:06 +00001382*/
sewardj8d1dc152010-10-08 17:43:26 +00001383#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
sewardjdfa55cf2010-10-06 22:07:06 +00001384# define __FRAME_POINTER \
sewardj8d1dc152010-10-08 17:43:26 +00001385 ,"r"(__builtin_dwarf_cfa())
sewardjdfa55cf2010-10-06 22:07:06 +00001386# define VALGRIND_CFI_PROLOGUE \
sewardjdfa55cf2010-10-06 22:07:06 +00001387 "movq %%rbp, %%r15\n\t" \
sewardj8d1dc152010-10-08 17:43:26 +00001388 "movq %2, %%rbp\n\t" \
1389 ".cfi_remember_state\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001390 ".cfi_def_cfa rbp, 0\n\t"
1391# define VALGRIND_CFI_EPILOGUE \
1392 "movq %%r15, %%rbp\n\t" \
1393 ".cfi_restore_state\n\t"
1394#else
1395# define __FRAME_POINTER
1396# define VALGRIND_CFI_PROLOGUE
1397# define VALGRIND_CFI_EPILOGUE
1398#endif
1399
tom4118e0f2012-08-02 09:23:45 +00001400/* Macros to save and align the stack before making a function
1401 call and restore it afterwards as gcc may not keep the stack
1402 pointer aligned if it doesn't realise calls are being made
1403 to other functions. */
1404
1405#define VALGRIND_ALIGN_STACK \
1406 "movq %%rsp,%%r14\n\t" \
1407 "andq $0xfffffffffffffff0,%%rsp\n\t"
1408#define VALGRIND_RESTORE_STACK \
1409 "movq %%r14,%%rsp\n\t"
sewardjdfa55cf2010-10-06 22:07:06 +00001410
sewardj0ec07f32006-01-12 12:32:32 +00001411/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1412 long) == 8. */
1413
sewardja07c2e12007-11-09 23:09:50 +00001414/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1415 macros. In order not to trash the stack redzone, we need to drop
1416 %rsp by 128 before the hidden call, and restore afterwards. The
1417 nastyness is that it is only by luck that the stack still appears
1418 to be unwindable during the hidden call - since then the behaviour
1419 of any routine using this macro does not match what the CFI data
1420 says. Sigh.
1421
1422 Why is this important? Imagine that a wrapper has a stack
1423 allocated local, and passes to the hidden call, a pointer to it.
1424 Because gcc does not know about the hidden call, it may allocate
1425 that local in the redzone. Unfortunately the hidden call may then
1426 trash it before it comes to use it. So we must step clear of the
1427 redzone, for the duration of the hidden call, to make it safe.
1428
1429 Probably the same problem afflicts the other redzone-style ABIs too
sewardj6e9de462011-06-28 07:25:29 +00001430 (ppc64-linux); but for those, the stack is
sewardja07c2e12007-11-09 23:09:50 +00001431 self describing (none of this CFI nonsense) so at least messing
1432 with the stack pointer doesn't give a danger of non-unwindable
1433 stack. */
1434
tom4118e0f2012-08-02 09:23:45 +00001435#define CALL_FN_W_v(lval, orig) \
1436 do { \
1437 volatile OrigFn _orig = (orig); \
1438 volatile unsigned long _argvec[1]; \
1439 volatile unsigned long _res; \
1440 _argvec[0] = (unsigned long)_orig.nraddr; \
1441 __asm__ volatile( \
1442 VALGRIND_CFI_PROLOGUE \
1443 VALGRIND_ALIGN_STACK \
1444 "subq $128,%%rsp\n\t" \
1445 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1446 VALGRIND_CALL_NOREDIR_RAX \
1447 VALGRIND_RESTORE_STACK \
1448 VALGRIND_CFI_EPILOGUE \
1449 : /*out*/ "=a" (_res) \
1450 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1451 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1452 ); \
1453 lval = (__typeof__(lval)) _res; \
sewardj0ec07f32006-01-12 12:32:32 +00001454 } while (0)
1455
tom4118e0f2012-08-02 09:23:45 +00001456#define CALL_FN_W_W(lval, orig, arg1) \
1457 do { \
1458 volatile OrigFn _orig = (orig); \
1459 volatile unsigned long _argvec[2]; \
1460 volatile unsigned long _res; \
1461 _argvec[0] = (unsigned long)_orig.nraddr; \
1462 _argvec[1] = (unsigned long)(arg1); \
1463 __asm__ volatile( \
1464 VALGRIND_CFI_PROLOGUE \
1465 VALGRIND_ALIGN_STACK \
1466 "subq $128,%%rsp\n\t" \
1467 "movq 8(%%rax), %%rdi\n\t" \
1468 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1469 VALGRIND_CALL_NOREDIR_RAX \
1470 VALGRIND_RESTORE_STACK \
1471 VALGRIND_CFI_EPILOGUE \
1472 : /*out*/ "=a" (_res) \
1473 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1474 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1475 ); \
1476 lval = (__typeof__(lval)) _res; \
sewardj0ec07f32006-01-12 12:32:32 +00001477 } while (0)
1478
tom4118e0f2012-08-02 09:23:45 +00001479#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1480 do { \
1481 volatile OrigFn _orig = (orig); \
1482 volatile unsigned long _argvec[3]; \
1483 volatile unsigned long _res; \
1484 _argvec[0] = (unsigned long)_orig.nraddr; \
1485 _argvec[1] = (unsigned long)(arg1); \
1486 _argvec[2] = (unsigned long)(arg2); \
1487 __asm__ volatile( \
1488 VALGRIND_CFI_PROLOGUE \
1489 VALGRIND_ALIGN_STACK \
1490 "subq $128,%%rsp\n\t" \
1491 "movq 16(%%rax), %%rsi\n\t" \
1492 "movq 8(%%rax), %%rdi\n\t" \
1493 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1494 VALGRIND_CALL_NOREDIR_RAX \
1495 VALGRIND_RESTORE_STACK \
1496 VALGRIND_CFI_EPILOGUE \
1497 : /*out*/ "=a" (_res) \
1498 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1499 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1500 ); \
1501 lval = (__typeof__(lval)) _res; \
sewardj0ec07f32006-01-12 12:32:32 +00001502 } while (0)
1503
tom4118e0f2012-08-02 09:23:45 +00001504#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1505 do { \
1506 volatile OrigFn _orig = (orig); \
1507 volatile unsigned long _argvec[4]; \
1508 volatile unsigned long _res; \
1509 _argvec[0] = (unsigned long)_orig.nraddr; \
1510 _argvec[1] = (unsigned long)(arg1); \
1511 _argvec[2] = (unsigned long)(arg2); \
1512 _argvec[3] = (unsigned long)(arg3); \
1513 __asm__ volatile( \
1514 VALGRIND_CFI_PROLOGUE \
1515 VALGRIND_ALIGN_STACK \
1516 "subq $128,%%rsp\n\t" \
1517 "movq 24(%%rax), %%rdx\n\t" \
1518 "movq 16(%%rax), %%rsi\n\t" \
1519 "movq 8(%%rax), %%rdi\n\t" \
1520 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1521 VALGRIND_CALL_NOREDIR_RAX \
1522 VALGRIND_RESTORE_STACK \
1523 VALGRIND_CFI_EPILOGUE \
1524 : /*out*/ "=a" (_res) \
1525 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1526 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1527 ); \
1528 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001529 } while (0)
1530
tom4118e0f2012-08-02 09:23:45 +00001531#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1532 do { \
1533 volatile OrigFn _orig = (orig); \
1534 volatile unsigned long _argvec[5]; \
1535 volatile unsigned long _res; \
1536 _argvec[0] = (unsigned long)_orig.nraddr; \
1537 _argvec[1] = (unsigned long)(arg1); \
1538 _argvec[2] = (unsigned long)(arg2); \
1539 _argvec[3] = (unsigned long)(arg3); \
1540 _argvec[4] = (unsigned long)(arg4); \
1541 __asm__ volatile( \
1542 VALGRIND_CFI_PROLOGUE \
1543 VALGRIND_ALIGN_STACK \
1544 "subq $128,%%rsp\n\t" \
1545 "movq 32(%%rax), %%rcx\n\t" \
1546 "movq 24(%%rax), %%rdx\n\t" \
1547 "movq 16(%%rax), %%rsi\n\t" \
1548 "movq 8(%%rax), %%rdi\n\t" \
1549 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1550 VALGRIND_CALL_NOREDIR_RAX \
1551 VALGRIND_RESTORE_STACK \
1552 VALGRIND_CFI_EPILOGUE \
1553 : /*out*/ "=a" (_res) \
1554 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1555 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1556 ); \
1557 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001558 } while (0)
1559
tom4118e0f2012-08-02 09:23:45 +00001560#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1561 do { \
1562 volatile OrigFn _orig = (orig); \
1563 volatile unsigned long _argvec[6]; \
1564 volatile unsigned long _res; \
1565 _argvec[0] = (unsigned long)_orig.nraddr; \
1566 _argvec[1] = (unsigned long)(arg1); \
1567 _argvec[2] = (unsigned long)(arg2); \
1568 _argvec[3] = (unsigned long)(arg3); \
1569 _argvec[4] = (unsigned long)(arg4); \
1570 _argvec[5] = (unsigned long)(arg5); \
1571 __asm__ volatile( \
1572 VALGRIND_CFI_PROLOGUE \
1573 VALGRIND_ALIGN_STACK \
1574 "subq $128,%%rsp\n\t" \
1575 "movq 40(%%rax), %%r8\n\t" \
1576 "movq 32(%%rax), %%rcx\n\t" \
1577 "movq 24(%%rax), %%rdx\n\t" \
1578 "movq 16(%%rax), %%rsi\n\t" \
1579 "movq 8(%%rax), %%rdi\n\t" \
1580 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1581 VALGRIND_CALL_NOREDIR_RAX \
1582 VALGRIND_RESTORE_STACK \
1583 VALGRIND_CFI_EPILOGUE \
1584 : /*out*/ "=a" (_res) \
1585 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1586 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1587 ); \
1588 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001589 } while (0)
1590
tom4118e0f2012-08-02 09:23:45 +00001591#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1592 do { \
1593 volatile OrigFn _orig = (orig); \
1594 volatile unsigned long _argvec[7]; \
1595 volatile unsigned long _res; \
1596 _argvec[0] = (unsigned long)_orig.nraddr; \
1597 _argvec[1] = (unsigned long)(arg1); \
1598 _argvec[2] = (unsigned long)(arg2); \
1599 _argvec[3] = (unsigned long)(arg3); \
1600 _argvec[4] = (unsigned long)(arg4); \
1601 _argvec[5] = (unsigned long)(arg5); \
1602 _argvec[6] = (unsigned long)(arg6); \
1603 __asm__ volatile( \
1604 VALGRIND_CFI_PROLOGUE \
1605 VALGRIND_ALIGN_STACK \
1606 "subq $128,%%rsp\n\t" \
1607 "movq 48(%%rax), %%r9\n\t" \
1608 "movq 40(%%rax), %%r8\n\t" \
1609 "movq 32(%%rax), %%rcx\n\t" \
1610 "movq 24(%%rax), %%rdx\n\t" \
1611 "movq 16(%%rax), %%rsi\n\t" \
1612 "movq 8(%%rax), %%rdi\n\t" \
1613 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1614 VALGRIND_CALL_NOREDIR_RAX \
1615 VALGRIND_RESTORE_STACK \
1616 VALGRIND_CFI_EPILOGUE \
1617 : /*out*/ "=a" (_res) \
1618 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1619 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1620 ); \
1621 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001622 } while (0)
1623
tom4118e0f2012-08-02 09:23:45 +00001624#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1625 arg7) \
1626 do { \
1627 volatile OrigFn _orig = (orig); \
1628 volatile unsigned long _argvec[8]; \
1629 volatile unsigned long _res; \
1630 _argvec[0] = (unsigned long)_orig.nraddr; \
1631 _argvec[1] = (unsigned long)(arg1); \
1632 _argvec[2] = (unsigned long)(arg2); \
1633 _argvec[3] = (unsigned long)(arg3); \
1634 _argvec[4] = (unsigned long)(arg4); \
1635 _argvec[5] = (unsigned long)(arg5); \
1636 _argvec[6] = (unsigned long)(arg6); \
1637 _argvec[7] = (unsigned long)(arg7); \
1638 __asm__ volatile( \
1639 VALGRIND_CFI_PROLOGUE \
1640 VALGRIND_ALIGN_STACK \
1641 "subq $136,%%rsp\n\t" \
1642 "pushq 56(%%rax)\n\t" \
1643 "movq 48(%%rax), %%r9\n\t" \
1644 "movq 40(%%rax), %%r8\n\t" \
1645 "movq 32(%%rax), %%rcx\n\t" \
1646 "movq 24(%%rax), %%rdx\n\t" \
1647 "movq 16(%%rax), %%rsi\n\t" \
1648 "movq 8(%%rax), %%rdi\n\t" \
1649 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1650 VALGRIND_CALL_NOREDIR_RAX \
1651 VALGRIND_RESTORE_STACK \
1652 VALGRIND_CFI_EPILOGUE \
1653 : /*out*/ "=a" (_res) \
1654 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1655 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1656 ); \
1657 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001658 } while (0)
1659
tom4118e0f2012-08-02 09:23:45 +00001660#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1661 arg7,arg8) \
1662 do { \
1663 volatile OrigFn _orig = (orig); \
1664 volatile unsigned long _argvec[9]; \
1665 volatile unsigned long _res; \
1666 _argvec[0] = (unsigned long)_orig.nraddr; \
1667 _argvec[1] = (unsigned long)(arg1); \
1668 _argvec[2] = (unsigned long)(arg2); \
1669 _argvec[3] = (unsigned long)(arg3); \
1670 _argvec[4] = (unsigned long)(arg4); \
1671 _argvec[5] = (unsigned long)(arg5); \
1672 _argvec[6] = (unsigned long)(arg6); \
1673 _argvec[7] = (unsigned long)(arg7); \
1674 _argvec[8] = (unsigned long)(arg8); \
1675 __asm__ volatile( \
1676 VALGRIND_CFI_PROLOGUE \
1677 VALGRIND_ALIGN_STACK \
1678 "subq $128,%%rsp\n\t" \
1679 "pushq 64(%%rax)\n\t" \
1680 "pushq 56(%%rax)\n\t" \
1681 "movq 48(%%rax), %%r9\n\t" \
1682 "movq 40(%%rax), %%r8\n\t" \
1683 "movq 32(%%rax), %%rcx\n\t" \
1684 "movq 24(%%rax), %%rdx\n\t" \
1685 "movq 16(%%rax), %%rsi\n\t" \
1686 "movq 8(%%rax), %%rdi\n\t" \
1687 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1688 VALGRIND_CALL_NOREDIR_RAX \
1689 VALGRIND_RESTORE_STACK \
1690 VALGRIND_CFI_EPILOGUE \
1691 : /*out*/ "=a" (_res) \
1692 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1693 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1694 ); \
1695 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001696 } while (0)
1697
tom4118e0f2012-08-02 09:23:45 +00001698#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1699 arg7,arg8,arg9) \
1700 do { \
1701 volatile OrigFn _orig = (orig); \
1702 volatile unsigned long _argvec[10]; \
1703 volatile unsigned long _res; \
1704 _argvec[0] = (unsigned long)_orig.nraddr; \
1705 _argvec[1] = (unsigned long)(arg1); \
1706 _argvec[2] = (unsigned long)(arg2); \
1707 _argvec[3] = (unsigned long)(arg3); \
1708 _argvec[4] = (unsigned long)(arg4); \
1709 _argvec[5] = (unsigned long)(arg5); \
1710 _argvec[6] = (unsigned long)(arg6); \
1711 _argvec[7] = (unsigned long)(arg7); \
1712 _argvec[8] = (unsigned long)(arg8); \
1713 _argvec[9] = (unsigned long)(arg9); \
1714 __asm__ volatile( \
1715 VALGRIND_CFI_PROLOGUE \
1716 VALGRIND_ALIGN_STACK \
1717 "subq $136,%%rsp\n\t" \
1718 "pushq 72(%%rax)\n\t" \
1719 "pushq 64(%%rax)\n\t" \
1720 "pushq 56(%%rax)\n\t" \
1721 "movq 48(%%rax), %%r9\n\t" \
1722 "movq 40(%%rax), %%r8\n\t" \
1723 "movq 32(%%rax), %%rcx\n\t" \
1724 "movq 24(%%rax), %%rdx\n\t" \
1725 "movq 16(%%rax), %%rsi\n\t" \
1726 "movq 8(%%rax), %%rdi\n\t" \
1727 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1728 VALGRIND_CALL_NOREDIR_RAX \
1729 VALGRIND_RESTORE_STACK \
1730 VALGRIND_CFI_EPILOGUE \
1731 : /*out*/ "=a" (_res) \
1732 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1733 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1734 ); \
1735 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001736 } while (0)
1737
tom4118e0f2012-08-02 09:23:45 +00001738#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1739 arg7,arg8,arg9,arg10) \
1740 do { \
1741 volatile OrigFn _orig = (orig); \
1742 volatile unsigned long _argvec[11]; \
1743 volatile unsigned long _res; \
1744 _argvec[0] = (unsigned long)_orig.nraddr; \
1745 _argvec[1] = (unsigned long)(arg1); \
1746 _argvec[2] = (unsigned long)(arg2); \
1747 _argvec[3] = (unsigned long)(arg3); \
1748 _argvec[4] = (unsigned long)(arg4); \
1749 _argvec[5] = (unsigned long)(arg5); \
1750 _argvec[6] = (unsigned long)(arg6); \
1751 _argvec[7] = (unsigned long)(arg7); \
1752 _argvec[8] = (unsigned long)(arg8); \
1753 _argvec[9] = (unsigned long)(arg9); \
1754 _argvec[10] = (unsigned long)(arg10); \
1755 __asm__ volatile( \
1756 VALGRIND_CFI_PROLOGUE \
1757 VALGRIND_ALIGN_STACK \
1758 "subq $128,%%rsp\n\t" \
1759 "pushq 80(%%rax)\n\t" \
1760 "pushq 72(%%rax)\n\t" \
1761 "pushq 64(%%rax)\n\t" \
1762 "pushq 56(%%rax)\n\t" \
1763 "movq 48(%%rax), %%r9\n\t" \
1764 "movq 40(%%rax), %%r8\n\t" \
1765 "movq 32(%%rax), %%rcx\n\t" \
1766 "movq 24(%%rax), %%rdx\n\t" \
1767 "movq 16(%%rax), %%rsi\n\t" \
1768 "movq 8(%%rax), %%rdi\n\t" \
1769 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1770 VALGRIND_CALL_NOREDIR_RAX \
1771 VALGRIND_RESTORE_STACK \
1772 VALGRIND_CFI_EPILOGUE \
1773 : /*out*/ "=a" (_res) \
1774 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1775 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1776 ); \
1777 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001778 } while (0)
1779
tom4118e0f2012-08-02 09:23:45 +00001780#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1781 arg7,arg8,arg9,arg10,arg11) \
1782 do { \
1783 volatile OrigFn _orig = (orig); \
1784 volatile unsigned long _argvec[12]; \
1785 volatile unsigned long _res; \
1786 _argvec[0] = (unsigned long)_orig.nraddr; \
1787 _argvec[1] = (unsigned long)(arg1); \
1788 _argvec[2] = (unsigned long)(arg2); \
1789 _argvec[3] = (unsigned long)(arg3); \
1790 _argvec[4] = (unsigned long)(arg4); \
1791 _argvec[5] = (unsigned long)(arg5); \
1792 _argvec[6] = (unsigned long)(arg6); \
1793 _argvec[7] = (unsigned long)(arg7); \
1794 _argvec[8] = (unsigned long)(arg8); \
1795 _argvec[9] = (unsigned long)(arg9); \
1796 _argvec[10] = (unsigned long)(arg10); \
1797 _argvec[11] = (unsigned long)(arg11); \
1798 __asm__ volatile( \
1799 VALGRIND_CFI_PROLOGUE \
1800 VALGRIND_ALIGN_STACK \
1801 "subq $136,%%rsp\n\t" \
1802 "pushq 88(%%rax)\n\t" \
1803 "pushq 80(%%rax)\n\t" \
1804 "pushq 72(%%rax)\n\t" \
1805 "pushq 64(%%rax)\n\t" \
1806 "pushq 56(%%rax)\n\t" \
1807 "movq 48(%%rax), %%r9\n\t" \
1808 "movq 40(%%rax), %%r8\n\t" \
1809 "movq 32(%%rax), %%rcx\n\t" \
1810 "movq 24(%%rax), %%rdx\n\t" \
1811 "movq 16(%%rax), %%rsi\n\t" \
1812 "movq 8(%%rax), %%rdi\n\t" \
1813 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1814 VALGRIND_CALL_NOREDIR_RAX \
1815 VALGRIND_RESTORE_STACK \
1816 VALGRIND_CFI_EPILOGUE \
1817 : /*out*/ "=a" (_res) \
1818 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1819 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1820 ); \
1821 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001822 } while (0)
1823
tom4118e0f2012-08-02 09:23:45 +00001824#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1825 arg7,arg8,arg9,arg10,arg11,arg12) \
1826 do { \
1827 volatile OrigFn _orig = (orig); \
1828 volatile unsigned long _argvec[13]; \
1829 volatile unsigned long _res; \
1830 _argvec[0] = (unsigned long)_orig.nraddr; \
1831 _argvec[1] = (unsigned long)(arg1); \
1832 _argvec[2] = (unsigned long)(arg2); \
1833 _argvec[3] = (unsigned long)(arg3); \
1834 _argvec[4] = (unsigned long)(arg4); \
1835 _argvec[5] = (unsigned long)(arg5); \
1836 _argvec[6] = (unsigned long)(arg6); \
1837 _argvec[7] = (unsigned long)(arg7); \
1838 _argvec[8] = (unsigned long)(arg8); \
1839 _argvec[9] = (unsigned long)(arg9); \
1840 _argvec[10] = (unsigned long)(arg10); \
1841 _argvec[11] = (unsigned long)(arg11); \
1842 _argvec[12] = (unsigned long)(arg12); \
1843 __asm__ volatile( \
1844 VALGRIND_CFI_PROLOGUE \
1845 VALGRIND_ALIGN_STACK \
1846 "subq $128,%%rsp\n\t" \
1847 "pushq 96(%%rax)\n\t" \
1848 "pushq 88(%%rax)\n\t" \
1849 "pushq 80(%%rax)\n\t" \
1850 "pushq 72(%%rax)\n\t" \
1851 "pushq 64(%%rax)\n\t" \
1852 "pushq 56(%%rax)\n\t" \
1853 "movq 48(%%rax), %%r9\n\t" \
1854 "movq 40(%%rax), %%r8\n\t" \
1855 "movq 32(%%rax), %%rcx\n\t" \
1856 "movq 24(%%rax), %%rdx\n\t" \
1857 "movq 16(%%rax), %%rsi\n\t" \
1858 "movq 8(%%rax), %%rdi\n\t" \
1859 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1860 VALGRIND_CALL_NOREDIR_RAX \
1861 VALGRIND_RESTORE_STACK \
1862 VALGRIND_CFI_EPILOGUE \
1863 : /*out*/ "=a" (_res) \
1864 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1865 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1866 ); \
1867 lval = (__typeof__(lval)) _res; \
sewardja50f9dc2006-03-11 16:19:14 +00001868 } while (0)
1869
njnf76d27a2009-05-28 01:53:07 +00001870#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001871
sewardjf5c1a7f2006-10-17 01:32:48 +00001872/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00001873
sewardjf5c1a7f2006-10-17 01:32:48 +00001874#if defined(PLAT_ppc32_linux)
sewardj0ec07f32006-01-12 12:32:32 +00001875
sewardjead61df2006-03-12 13:39:15 +00001876/* This is useful for finding out about the on-stack stuff:
1877
1878 extern int f9 ( int,int,int,int,int,int,int,int,int );
1879 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1880 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1881 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1882
1883 int g9 ( void ) {
1884 return f9(11,22,33,44,55,66,77,88,99);
1885 }
1886 int g10 ( void ) {
1887 return f10(11,22,33,44,55,66,77,88,99,110);
1888 }
1889 int g11 ( void ) {
1890 return f11(11,22,33,44,55,66,77,88,99,110,121);
1891 }
1892 int g12 ( void ) {
1893 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1894 }
1895*/
1896
sewardj0ec07f32006-01-12 12:32:32 +00001897/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1898
1899/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00001900#define __CALLER_SAVED_REGS \
1901 "lr", "ctr", "xer", \
1902 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1903 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1904 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00001905
tom4118e0f2012-08-02 09:23:45 +00001906/* Macros to save and align the stack before making a function
1907 call and restore it afterwards as gcc may not keep the stack
1908 pointer aligned if it doesn't realise calls are being made
1909 to other functions. */
1910
1911#define VALGRIND_ALIGN_STACK \
1912 "mr 28,1\n\t" \
1913 "rlwinm 1,1,0,0,27\n\t"
1914#define VALGRIND_RESTORE_STACK \
1915 "mr 1,28\n\t"
1916
sewardjead61df2006-03-12 13:39:15 +00001917/* These CALL_FN_ macros assume that on ppc32-linux,
1918 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00001919
sewardj38de0992006-01-20 16:46:34 +00001920#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001921 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001922 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001923 volatile unsigned long _argvec[1]; \
1924 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001925 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001926 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001927 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001928 "mr 11,%1\n\t" \
1929 "lwz 11,0(11)\n\t" /* target->r11 */ \
1930 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00001931 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001932 "mr %0,3" \
1933 : /*out*/ "=r" (_res) \
1934 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001935 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj0ec07f32006-01-12 12:32:32 +00001936 ); \
1937 lval = (__typeof__(lval)) _res; \
1938 } while (0)
1939
sewardj38de0992006-01-20 16:46:34 +00001940#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001941 do { \
sewardj38de0992006-01-20 16:46:34 +00001942 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001943 volatile unsigned long _argvec[2]; \
1944 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001945 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001946 _argvec[1] = (unsigned long)arg1; \
1947 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001948 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001949 "mr 11,%1\n\t" \
1950 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1951 "lwz 11,0(11)\n\t" /* target->r11 */ \
1952 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00001953 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001954 "mr %0,3" \
1955 : /*out*/ "=r" (_res) \
1956 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001957 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj0ec07f32006-01-12 12:32:32 +00001958 ); \
1959 lval = (__typeof__(lval)) _res; \
1960 } while (0)
1961
sewardj38de0992006-01-20 16:46:34 +00001962#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001963 do { \
sewardj38de0992006-01-20 16:46:34 +00001964 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001965 volatile unsigned long _argvec[3]; \
1966 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001967 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001968 _argvec[1] = (unsigned long)arg1; \
1969 _argvec[2] = (unsigned long)arg2; \
1970 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001971 VALGRIND_ALIGN_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001972 "mr 11,%1\n\t" \
1973 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1974 "lwz 4,8(11)\n\t" \
1975 "lwz 11,0(11)\n\t" /* target->r11 */ \
1976 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00001977 VALGRIND_RESTORE_STACK \
sewardj0ec07f32006-01-12 12:32:32 +00001978 "mr %0,3" \
1979 : /*out*/ "=r" (_res) \
1980 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00001981 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj0ec07f32006-01-12 12:32:32 +00001982 ); \
1983 lval = (__typeof__(lval)) _res; \
1984 } while (0)
1985
sewardjead61df2006-03-12 13:39:15 +00001986#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1987 do { \
1988 volatile OrigFn _orig = (orig); \
1989 volatile unsigned long _argvec[4]; \
1990 volatile unsigned long _res; \
1991 _argvec[0] = (unsigned long)_orig.nraddr; \
1992 _argvec[1] = (unsigned long)arg1; \
1993 _argvec[2] = (unsigned long)arg2; \
1994 _argvec[3] = (unsigned long)arg3; \
1995 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00001996 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00001997 "mr 11,%1\n\t" \
1998 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1999 "lwz 4,8(11)\n\t" \
2000 "lwz 5,12(11)\n\t" \
2001 "lwz 11,0(11)\n\t" /* target->r11 */ \
2002 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002003 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002004 "mr %0,3" \
2005 : /*out*/ "=r" (_res) \
2006 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002007 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002008 ); \
2009 lval = (__typeof__(lval)) _res; \
2010 } while (0)
2011
2012#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2013 do { \
2014 volatile OrigFn _orig = (orig); \
2015 volatile unsigned long _argvec[5]; \
2016 volatile unsigned long _res; \
2017 _argvec[0] = (unsigned long)_orig.nraddr; \
2018 _argvec[1] = (unsigned long)arg1; \
2019 _argvec[2] = (unsigned long)arg2; \
2020 _argvec[3] = (unsigned long)arg3; \
2021 _argvec[4] = (unsigned long)arg4; \
2022 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002023 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002024 "mr 11,%1\n\t" \
2025 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2026 "lwz 4,8(11)\n\t" \
2027 "lwz 5,12(11)\n\t" \
2028 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2029 "lwz 11,0(11)\n\t" /* target->r11 */ \
2030 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002031 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002032 "mr %0,3" \
2033 : /*out*/ "=r" (_res) \
2034 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002035 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002036 ); \
2037 lval = (__typeof__(lval)) _res; \
2038 } while (0)
2039
2040#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2041 do { \
2042 volatile OrigFn _orig = (orig); \
2043 volatile unsigned long _argvec[6]; \
2044 volatile unsigned long _res; \
2045 _argvec[0] = (unsigned long)_orig.nraddr; \
2046 _argvec[1] = (unsigned long)arg1; \
2047 _argvec[2] = (unsigned long)arg2; \
2048 _argvec[3] = (unsigned long)arg3; \
2049 _argvec[4] = (unsigned long)arg4; \
2050 _argvec[5] = (unsigned long)arg5; \
2051 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002052 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002053 "mr 11,%1\n\t" \
2054 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2055 "lwz 4,8(11)\n\t" \
2056 "lwz 5,12(11)\n\t" \
2057 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2058 "lwz 7,20(11)\n\t" \
2059 "lwz 11,0(11)\n\t" /* target->r11 */ \
2060 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002061 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002062 "mr %0,3" \
2063 : /*out*/ "=r" (_res) \
2064 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002065 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002066 ); \
2067 lval = (__typeof__(lval)) _res; \
2068 } while (0)
2069
2070#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2071 do { \
2072 volatile OrigFn _orig = (orig); \
2073 volatile unsigned long _argvec[7]; \
2074 volatile unsigned long _res; \
2075 _argvec[0] = (unsigned long)_orig.nraddr; \
2076 _argvec[1] = (unsigned long)arg1; \
2077 _argvec[2] = (unsigned long)arg2; \
2078 _argvec[3] = (unsigned long)arg3; \
2079 _argvec[4] = (unsigned long)arg4; \
2080 _argvec[5] = (unsigned long)arg5; \
2081 _argvec[6] = (unsigned long)arg6; \
2082 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002083 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002084 "mr 11,%1\n\t" \
2085 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2086 "lwz 4,8(11)\n\t" \
2087 "lwz 5,12(11)\n\t" \
2088 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2089 "lwz 7,20(11)\n\t" \
2090 "lwz 8,24(11)\n\t" \
2091 "lwz 11,0(11)\n\t" /* target->r11 */ \
2092 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002093 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002094 "mr %0,3" \
2095 : /*out*/ "=r" (_res) \
2096 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002097 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002098 ); \
2099 lval = (__typeof__(lval)) _res; \
2100 } while (0)
2101
2102#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2103 arg7) \
2104 do { \
2105 volatile OrigFn _orig = (orig); \
2106 volatile unsigned long _argvec[8]; \
2107 volatile unsigned long _res; \
2108 _argvec[0] = (unsigned long)_orig.nraddr; \
2109 _argvec[1] = (unsigned long)arg1; \
2110 _argvec[2] = (unsigned long)arg2; \
2111 _argvec[3] = (unsigned long)arg3; \
2112 _argvec[4] = (unsigned long)arg4; \
2113 _argvec[5] = (unsigned long)arg5; \
2114 _argvec[6] = (unsigned long)arg6; \
2115 _argvec[7] = (unsigned long)arg7; \
2116 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002117 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002118 "mr 11,%1\n\t" \
2119 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2120 "lwz 4,8(11)\n\t" \
2121 "lwz 5,12(11)\n\t" \
2122 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2123 "lwz 7,20(11)\n\t" \
2124 "lwz 8,24(11)\n\t" \
2125 "lwz 9,28(11)\n\t" \
2126 "lwz 11,0(11)\n\t" /* target->r11 */ \
2127 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002128 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002129 "mr %0,3" \
2130 : /*out*/ "=r" (_res) \
2131 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002132 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002133 ); \
2134 lval = (__typeof__(lval)) _res; \
2135 } while (0)
2136
2137#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2138 arg7,arg8) \
2139 do { \
2140 volatile OrigFn _orig = (orig); \
2141 volatile unsigned long _argvec[9]; \
2142 volatile unsigned long _res; \
2143 _argvec[0] = (unsigned long)_orig.nraddr; \
2144 _argvec[1] = (unsigned long)arg1; \
2145 _argvec[2] = (unsigned long)arg2; \
2146 _argvec[3] = (unsigned long)arg3; \
2147 _argvec[4] = (unsigned long)arg4; \
2148 _argvec[5] = (unsigned long)arg5; \
2149 _argvec[6] = (unsigned long)arg6; \
2150 _argvec[7] = (unsigned long)arg7; \
2151 _argvec[8] = (unsigned long)arg8; \
2152 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002153 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002154 "mr 11,%1\n\t" \
2155 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2156 "lwz 4,8(11)\n\t" \
2157 "lwz 5,12(11)\n\t" \
2158 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2159 "lwz 7,20(11)\n\t" \
2160 "lwz 8,24(11)\n\t" \
2161 "lwz 9,28(11)\n\t" \
2162 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2163 "lwz 11,0(11)\n\t" /* target->r11 */ \
2164 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002165 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002166 "mr %0,3" \
2167 : /*out*/ "=r" (_res) \
2168 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002169 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002170 ); \
2171 lval = (__typeof__(lval)) _res; \
2172 } while (0)
2173
2174#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2175 arg7,arg8,arg9) \
2176 do { \
2177 volatile OrigFn _orig = (orig); \
2178 volatile unsigned long _argvec[10]; \
2179 volatile unsigned long _res; \
2180 _argvec[0] = (unsigned long)_orig.nraddr; \
2181 _argvec[1] = (unsigned long)arg1; \
2182 _argvec[2] = (unsigned long)arg2; \
2183 _argvec[3] = (unsigned long)arg3; \
2184 _argvec[4] = (unsigned long)arg4; \
2185 _argvec[5] = (unsigned long)arg5; \
2186 _argvec[6] = (unsigned long)arg6; \
2187 _argvec[7] = (unsigned long)arg7; \
2188 _argvec[8] = (unsigned long)arg8; \
2189 _argvec[9] = (unsigned long)arg9; \
2190 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002191 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002192 "mr 11,%1\n\t" \
2193 "addi 1,1,-16\n\t" \
2194 /* arg9 */ \
2195 "lwz 3,36(11)\n\t" \
2196 "stw 3,8(1)\n\t" \
2197 /* args1-8 */ \
2198 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2199 "lwz 4,8(11)\n\t" \
2200 "lwz 5,12(11)\n\t" \
2201 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2202 "lwz 7,20(11)\n\t" \
2203 "lwz 8,24(11)\n\t" \
2204 "lwz 9,28(11)\n\t" \
2205 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2206 "lwz 11,0(11)\n\t" /* target->r11 */ \
2207 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002208 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002209 "mr %0,3" \
2210 : /*out*/ "=r" (_res) \
2211 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002212 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002213 ); \
2214 lval = (__typeof__(lval)) _res; \
2215 } while (0)
2216
2217#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2218 arg7,arg8,arg9,arg10) \
2219 do { \
2220 volatile OrigFn _orig = (orig); \
2221 volatile unsigned long _argvec[11]; \
2222 volatile unsigned long _res; \
2223 _argvec[0] = (unsigned long)_orig.nraddr; \
2224 _argvec[1] = (unsigned long)arg1; \
2225 _argvec[2] = (unsigned long)arg2; \
2226 _argvec[3] = (unsigned long)arg3; \
2227 _argvec[4] = (unsigned long)arg4; \
2228 _argvec[5] = (unsigned long)arg5; \
2229 _argvec[6] = (unsigned long)arg6; \
2230 _argvec[7] = (unsigned long)arg7; \
2231 _argvec[8] = (unsigned long)arg8; \
2232 _argvec[9] = (unsigned long)arg9; \
2233 _argvec[10] = (unsigned long)arg10; \
2234 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002235 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002236 "mr 11,%1\n\t" \
2237 "addi 1,1,-16\n\t" \
2238 /* arg10 */ \
2239 "lwz 3,40(11)\n\t" \
2240 "stw 3,12(1)\n\t" \
2241 /* arg9 */ \
2242 "lwz 3,36(11)\n\t" \
2243 "stw 3,8(1)\n\t" \
2244 /* args1-8 */ \
2245 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2246 "lwz 4,8(11)\n\t" \
2247 "lwz 5,12(11)\n\t" \
2248 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2249 "lwz 7,20(11)\n\t" \
2250 "lwz 8,24(11)\n\t" \
2251 "lwz 9,28(11)\n\t" \
2252 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2253 "lwz 11,0(11)\n\t" /* target->r11 */ \
2254 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002255 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002256 "mr %0,3" \
2257 : /*out*/ "=r" (_res) \
2258 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002259 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002260 ); \
2261 lval = (__typeof__(lval)) _res; \
2262 } while (0)
2263
2264#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2265 arg7,arg8,arg9,arg10,arg11) \
2266 do { \
2267 volatile OrigFn _orig = (orig); \
2268 volatile unsigned long _argvec[12]; \
2269 volatile unsigned long _res; \
2270 _argvec[0] = (unsigned long)_orig.nraddr; \
2271 _argvec[1] = (unsigned long)arg1; \
2272 _argvec[2] = (unsigned long)arg2; \
2273 _argvec[3] = (unsigned long)arg3; \
2274 _argvec[4] = (unsigned long)arg4; \
2275 _argvec[5] = (unsigned long)arg5; \
2276 _argvec[6] = (unsigned long)arg6; \
2277 _argvec[7] = (unsigned long)arg7; \
2278 _argvec[8] = (unsigned long)arg8; \
2279 _argvec[9] = (unsigned long)arg9; \
2280 _argvec[10] = (unsigned long)arg10; \
2281 _argvec[11] = (unsigned long)arg11; \
2282 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002283 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002284 "mr 11,%1\n\t" \
2285 "addi 1,1,-32\n\t" \
2286 /* arg11 */ \
2287 "lwz 3,44(11)\n\t" \
2288 "stw 3,16(1)\n\t" \
2289 /* arg10 */ \
2290 "lwz 3,40(11)\n\t" \
2291 "stw 3,12(1)\n\t" \
2292 /* arg9 */ \
2293 "lwz 3,36(11)\n\t" \
2294 "stw 3,8(1)\n\t" \
2295 /* args1-8 */ \
2296 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2297 "lwz 4,8(11)\n\t" \
2298 "lwz 5,12(11)\n\t" \
2299 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2300 "lwz 7,20(11)\n\t" \
2301 "lwz 8,24(11)\n\t" \
2302 "lwz 9,28(11)\n\t" \
2303 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2304 "lwz 11,0(11)\n\t" /* target->r11 */ \
2305 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002306 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002307 "mr %0,3" \
2308 : /*out*/ "=r" (_res) \
2309 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002310 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002311 ); \
2312 lval = (__typeof__(lval)) _res; \
2313 } while (0)
2314
2315#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2316 arg7,arg8,arg9,arg10,arg11,arg12) \
2317 do { \
2318 volatile OrigFn _orig = (orig); \
2319 volatile unsigned long _argvec[13]; \
2320 volatile unsigned long _res; \
2321 _argvec[0] = (unsigned long)_orig.nraddr; \
2322 _argvec[1] = (unsigned long)arg1; \
2323 _argvec[2] = (unsigned long)arg2; \
2324 _argvec[3] = (unsigned long)arg3; \
2325 _argvec[4] = (unsigned long)arg4; \
2326 _argvec[5] = (unsigned long)arg5; \
2327 _argvec[6] = (unsigned long)arg6; \
2328 _argvec[7] = (unsigned long)arg7; \
2329 _argvec[8] = (unsigned long)arg8; \
2330 _argvec[9] = (unsigned long)arg9; \
2331 _argvec[10] = (unsigned long)arg10; \
2332 _argvec[11] = (unsigned long)arg11; \
2333 _argvec[12] = (unsigned long)arg12; \
2334 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002335 VALGRIND_ALIGN_STACK \
sewardjead61df2006-03-12 13:39:15 +00002336 "mr 11,%1\n\t" \
2337 "addi 1,1,-32\n\t" \
2338 /* arg12 */ \
2339 "lwz 3,48(11)\n\t" \
2340 "stw 3,20(1)\n\t" \
2341 /* arg11 */ \
2342 "lwz 3,44(11)\n\t" \
2343 "stw 3,16(1)\n\t" \
2344 /* arg10 */ \
2345 "lwz 3,40(11)\n\t" \
2346 "stw 3,12(1)\n\t" \
2347 /* arg9 */ \
2348 "lwz 3,36(11)\n\t" \
2349 "stw 3,8(1)\n\t" \
2350 /* args1-8 */ \
2351 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2352 "lwz 4,8(11)\n\t" \
2353 "lwz 5,12(11)\n\t" \
2354 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2355 "lwz 7,20(11)\n\t" \
2356 "lwz 8,24(11)\n\t" \
2357 "lwz 9,28(11)\n\t" \
2358 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2359 "lwz 11,0(11)\n\t" /* target->r11 */ \
2360 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
tom4118e0f2012-08-02 09:23:45 +00002361 VALGRIND_RESTORE_STACK \
sewardjead61df2006-03-12 13:39:15 +00002362 "mr %0,3" \
2363 : /*out*/ "=r" (_res) \
2364 : /*in*/ "r" (&_argvec[0]) \
tom4118e0f2012-08-02 09:23:45 +00002365 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjead61df2006-03-12 13:39:15 +00002366 ); \
2367 lval = (__typeof__(lval)) _res; \
2368 } while (0)
2369
sewardjf5c1a7f2006-10-17 01:32:48 +00002370#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +00002371
sewardjf5c1a7f2006-10-17 01:32:48 +00002372/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002373
sewardjf5c1a7f2006-10-17 01:32:48 +00002374#if defined(PLAT_ppc64_linux)
sewardj9734b202006-01-17 01:49:37 +00002375
2376/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2377
2378/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00002379#define __CALLER_SAVED_REGS \
2380 "lr", "ctr", "xer", \
2381 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2382 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2383 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00002384
tom4118e0f2012-08-02 09:23:45 +00002385/* Macros to save and align the stack before making a function
2386 call and restore it afterwards as gcc may not keep the stack
2387 pointer aligned if it doesn't realise calls are being made
2388 to other functions. */
2389
2390#define VALGRIND_ALIGN_STACK \
2391 "mr 28,1\n\t" \
2392 "rldicr 1,1,0,59\n\t"
2393#define VALGRIND_RESTORE_STACK \
2394 "mr 1,28\n\t"
2395
sewardj9734b202006-01-17 01:49:37 +00002396/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2397 long) == 8. */
2398
sewardjd68ac3e2006-01-20 14:31:57 +00002399#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00002400 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002401 volatile OrigFn _orig = (orig); \
2402 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00002403 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002404 /* _argvec[0] holds current r2 across the call */ \
2405 _argvec[1] = (unsigned long)_orig.r2; \
2406 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00002407 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002408 VALGRIND_ALIGN_STACK \
sewardj9734b202006-01-17 01:49:37 +00002409 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002410 "std 2,-16(11)\n\t" /* save tocptr */ \
2411 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2412 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002413 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2414 "mr 11,%1\n\t" \
2415 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002416 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2417 VALGRIND_RESTORE_STACK \
sewardj9734b202006-01-17 01:49:37 +00002418 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002419 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002420 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj9734b202006-01-17 01:49:37 +00002421 ); \
2422 lval = (__typeof__(lval)) _res; \
2423 } while (0)
2424
sewardjd68ac3e2006-01-20 14:31:57 +00002425#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00002426 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002427 volatile OrigFn _orig = (orig); \
2428 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00002429 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002430 /* _argvec[0] holds current r2 across the call */ \
2431 _argvec[1] = (unsigned long)_orig.r2; \
2432 _argvec[2] = (unsigned long)_orig.nraddr; \
2433 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00002434 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002435 VALGRIND_ALIGN_STACK \
sewardj9734b202006-01-17 01:49:37 +00002436 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002437 "std 2,-16(11)\n\t" /* save tocptr */ \
2438 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2439 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2440 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002441 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2442 "mr 11,%1\n\t" \
2443 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002444 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2445 VALGRIND_RESTORE_STACK \
sewardj9734b202006-01-17 01:49:37 +00002446 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002447 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002448 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj9734b202006-01-17 01:49:37 +00002449 ); \
2450 lval = (__typeof__(lval)) _res; \
2451 } while (0)
2452
sewardjd68ac3e2006-01-20 14:31:57 +00002453#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00002454 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002455 volatile OrigFn _orig = (orig); \
2456 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00002457 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002458 /* _argvec[0] holds current r2 across the call */ \
2459 _argvec[1] = (unsigned long)_orig.r2; \
2460 _argvec[2] = (unsigned long)_orig.nraddr; \
2461 _argvec[2+1] = (unsigned long)arg1; \
2462 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00002463 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002464 VALGRIND_ALIGN_STACK \
sewardj9734b202006-01-17 01:49:37 +00002465 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002466 "std 2,-16(11)\n\t" /* save tocptr */ \
2467 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2468 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00002469 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00002470 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002471 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2472 "mr 11,%1\n\t" \
2473 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002474 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2475 VALGRIND_RESTORE_STACK \
sewardj9734b202006-01-17 01:49:37 +00002476 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002477 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002478 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardj9734b202006-01-17 01:49:37 +00002479 ); \
2480 lval = (__typeof__(lval)) _res; \
2481 } while (0)
2482
sewardjcd636392006-03-12 16:48:14 +00002483#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2484 do { \
2485 volatile OrigFn _orig = (orig); \
2486 volatile unsigned long _argvec[3+3]; \
2487 volatile unsigned long _res; \
2488 /* _argvec[0] holds current r2 across the call */ \
2489 _argvec[1] = (unsigned long)_orig.r2; \
2490 _argvec[2] = (unsigned long)_orig.nraddr; \
2491 _argvec[2+1] = (unsigned long)arg1; \
2492 _argvec[2+2] = (unsigned long)arg2; \
2493 _argvec[2+3] = (unsigned long)arg3; \
2494 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002495 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002496 "mr 11,%1\n\t" \
2497 "std 2,-16(11)\n\t" /* save tocptr */ \
2498 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2499 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2500 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2501 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2502 "ld 11, 0(11)\n\t" /* target->r11 */ \
2503 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2504 "mr 11,%1\n\t" \
2505 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002506 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2507 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002508 : /*out*/ "=r" (_res) \
2509 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002510 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002511 ); \
2512 lval = (__typeof__(lval)) _res; \
2513 } while (0)
2514
2515#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2516 do { \
2517 volatile OrigFn _orig = (orig); \
2518 volatile unsigned long _argvec[3+4]; \
2519 volatile unsigned long _res; \
2520 /* _argvec[0] holds current r2 across the call */ \
2521 _argvec[1] = (unsigned long)_orig.r2; \
2522 _argvec[2] = (unsigned long)_orig.nraddr; \
2523 _argvec[2+1] = (unsigned long)arg1; \
2524 _argvec[2+2] = (unsigned long)arg2; \
2525 _argvec[2+3] = (unsigned long)arg3; \
2526 _argvec[2+4] = (unsigned long)arg4; \
2527 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002528 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002529 "mr 11,%1\n\t" \
2530 "std 2,-16(11)\n\t" /* save tocptr */ \
2531 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2532 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2533 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2534 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2535 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2536 "ld 11, 0(11)\n\t" /* target->r11 */ \
2537 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2538 "mr 11,%1\n\t" \
2539 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002540 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2541 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002542 : /*out*/ "=r" (_res) \
2543 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002544 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002545 ); \
2546 lval = (__typeof__(lval)) _res; \
2547 } while (0)
2548
2549#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2550 do { \
2551 volatile OrigFn _orig = (orig); \
2552 volatile unsigned long _argvec[3+5]; \
2553 volatile unsigned long _res; \
2554 /* _argvec[0] holds current r2 across the call */ \
2555 _argvec[1] = (unsigned long)_orig.r2; \
2556 _argvec[2] = (unsigned long)_orig.nraddr; \
2557 _argvec[2+1] = (unsigned long)arg1; \
2558 _argvec[2+2] = (unsigned long)arg2; \
2559 _argvec[2+3] = (unsigned long)arg3; \
2560 _argvec[2+4] = (unsigned long)arg4; \
2561 _argvec[2+5] = (unsigned long)arg5; \
2562 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002563 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002564 "mr 11,%1\n\t" \
2565 "std 2,-16(11)\n\t" /* save tocptr */ \
2566 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2567 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2568 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2569 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2570 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2571 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2572 "ld 11, 0(11)\n\t" /* target->r11 */ \
2573 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2574 "mr 11,%1\n\t" \
2575 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002576 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2577 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002578 : /*out*/ "=r" (_res) \
2579 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002580 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002581 ); \
2582 lval = (__typeof__(lval)) _res; \
2583 } while (0)
2584
2585#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2586 do { \
2587 volatile OrigFn _orig = (orig); \
2588 volatile unsigned long _argvec[3+6]; \
2589 volatile unsigned long _res; \
2590 /* _argvec[0] holds current r2 across the call */ \
2591 _argvec[1] = (unsigned long)_orig.r2; \
2592 _argvec[2] = (unsigned long)_orig.nraddr; \
2593 _argvec[2+1] = (unsigned long)arg1; \
2594 _argvec[2+2] = (unsigned long)arg2; \
2595 _argvec[2+3] = (unsigned long)arg3; \
2596 _argvec[2+4] = (unsigned long)arg4; \
2597 _argvec[2+5] = (unsigned long)arg5; \
2598 _argvec[2+6] = (unsigned long)arg6; \
2599 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002600 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002601 "mr 11,%1\n\t" \
2602 "std 2,-16(11)\n\t" /* save tocptr */ \
2603 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2604 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2605 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2606 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2607 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2608 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2609 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2610 "ld 11, 0(11)\n\t" /* target->r11 */ \
2611 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2612 "mr 11,%1\n\t" \
2613 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002614 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2615 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002616 : /*out*/ "=r" (_res) \
2617 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002618 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002619 ); \
2620 lval = (__typeof__(lval)) _res; \
2621 } while (0)
2622
2623#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2624 arg7) \
2625 do { \
2626 volatile OrigFn _orig = (orig); \
2627 volatile unsigned long _argvec[3+7]; \
2628 volatile unsigned long _res; \
2629 /* _argvec[0] holds current r2 across the call */ \
2630 _argvec[1] = (unsigned long)_orig.r2; \
2631 _argvec[2] = (unsigned long)_orig.nraddr; \
2632 _argvec[2+1] = (unsigned long)arg1; \
2633 _argvec[2+2] = (unsigned long)arg2; \
2634 _argvec[2+3] = (unsigned long)arg3; \
2635 _argvec[2+4] = (unsigned long)arg4; \
2636 _argvec[2+5] = (unsigned long)arg5; \
2637 _argvec[2+6] = (unsigned long)arg6; \
2638 _argvec[2+7] = (unsigned long)arg7; \
2639 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002640 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002641 "mr 11,%1\n\t" \
2642 "std 2,-16(11)\n\t" /* save tocptr */ \
2643 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2644 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2645 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2646 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2647 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2648 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2649 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2650 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2651 "ld 11, 0(11)\n\t" /* target->r11 */ \
2652 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2653 "mr 11,%1\n\t" \
2654 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002655 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2656 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002657 : /*out*/ "=r" (_res) \
2658 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002659 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002660 ); \
2661 lval = (__typeof__(lval)) _res; \
2662 } while (0)
2663
2664#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2665 arg7,arg8) \
2666 do { \
2667 volatile OrigFn _orig = (orig); \
2668 volatile unsigned long _argvec[3+8]; \
2669 volatile unsigned long _res; \
2670 /* _argvec[0] holds current r2 across the call */ \
2671 _argvec[1] = (unsigned long)_orig.r2; \
2672 _argvec[2] = (unsigned long)_orig.nraddr; \
2673 _argvec[2+1] = (unsigned long)arg1; \
2674 _argvec[2+2] = (unsigned long)arg2; \
2675 _argvec[2+3] = (unsigned long)arg3; \
2676 _argvec[2+4] = (unsigned long)arg4; \
2677 _argvec[2+5] = (unsigned long)arg5; \
2678 _argvec[2+6] = (unsigned long)arg6; \
2679 _argvec[2+7] = (unsigned long)arg7; \
2680 _argvec[2+8] = (unsigned long)arg8; \
2681 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002682 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002683 "mr 11,%1\n\t" \
2684 "std 2,-16(11)\n\t" /* save tocptr */ \
2685 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2686 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2687 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2688 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2689 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2690 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2691 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2692 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2693 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2694 "ld 11, 0(11)\n\t" /* target->r11 */ \
2695 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2696 "mr 11,%1\n\t" \
2697 "mr %0,3\n\t" \
tom4118e0f2012-08-02 09:23:45 +00002698 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2699 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002700 : /*out*/ "=r" (_res) \
2701 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002702 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002703 ); \
2704 lval = (__typeof__(lval)) _res; \
2705 } while (0)
2706
2707#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2708 arg7,arg8,arg9) \
2709 do { \
2710 volatile OrigFn _orig = (orig); \
2711 volatile unsigned long _argvec[3+9]; \
2712 volatile unsigned long _res; \
2713 /* _argvec[0] holds current r2 across the call */ \
2714 _argvec[1] = (unsigned long)_orig.r2; \
2715 _argvec[2] = (unsigned long)_orig.nraddr; \
2716 _argvec[2+1] = (unsigned long)arg1; \
2717 _argvec[2+2] = (unsigned long)arg2; \
2718 _argvec[2+3] = (unsigned long)arg3; \
2719 _argvec[2+4] = (unsigned long)arg4; \
2720 _argvec[2+5] = (unsigned long)arg5; \
2721 _argvec[2+6] = (unsigned long)arg6; \
2722 _argvec[2+7] = (unsigned long)arg7; \
2723 _argvec[2+8] = (unsigned long)arg8; \
2724 _argvec[2+9] = (unsigned long)arg9; \
2725 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002726 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002727 "mr 11,%1\n\t" \
2728 "std 2,-16(11)\n\t" /* save tocptr */ \
2729 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2730 "addi 1,1,-128\n\t" /* expand stack frame */ \
2731 /* arg9 */ \
2732 "ld 3,72(11)\n\t" \
2733 "std 3,112(1)\n\t" \
2734 /* args1-8 */ \
2735 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2736 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2737 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2738 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2739 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2740 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2741 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2742 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2743 "ld 11, 0(11)\n\t" /* target->r11 */ \
2744 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2745 "mr 11,%1\n\t" \
2746 "mr %0,3\n\t" \
2747 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00002748 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002749 : /*out*/ "=r" (_res) \
2750 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002751 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002752 ); \
2753 lval = (__typeof__(lval)) _res; \
2754 } while (0)
2755
2756#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2757 arg7,arg8,arg9,arg10) \
2758 do { \
2759 volatile OrigFn _orig = (orig); \
2760 volatile unsigned long _argvec[3+10]; \
2761 volatile unsigned long _res; \
2762 /* _argvec[0] holds current r2 across the call */ \
2763 _argvec[1] = (unsigned long)_orig.r2; \
2764 _argvec[2] = (unsigned long)_orig.nraddr; \
2765 _argvec[2+1] = (unsigned long)arg1; \
2766 _argvec[2+2] = (unsigned long)arg2; \
2767 _argvec[2+3] = (unsigned long)arg3; \
2768 _argvec[2+4] = (unsigned long)arg4; \
2769 _argvec[2+5] = (unsigned long)arg5; \
2770 _argvec[2+6] = (unsigned long)arg6; \
2771 _argvec[2+7] = (unsigned long)arg7; \
2772 _argvec[2+8] = (unsigned long)arg8; \
2773 _argvec[2+9] = (unsigned long)arg9; \
2774 _argvec[2+10] = (unsigned long)arg10; \
2775 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002776 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002777 "mr 11,%1\n\t" \
2778 "std 2,-16(11)\n\t" /* save tocptr */ \
2779 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2780 "addi 1,1,-128\n\t" /* expand stack frame */ \
2781 /* arg10 */ \
2782 "ld 3,80(11)\n\t" \
2783 "std 3,120(1)\n\t" \
2784 /* arg9 */ \
2785 "ld 3,72(11)\n\t" \
2786 "std 3,112(1)\n\t" \
2787 /* args1-8 */ \
2788 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2789 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2790 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2791 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2792 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2793 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2794 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2795 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2796 "ld 11, 0(11)\n\t" /* target->r11 */ \
2797 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2798 "mr 11,%1\n\t" \
2799 "mr %0,3\n\t" \
2800 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00002801 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002802 : /*out*/ "=r" (_res) \
2803 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002804 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002805 ); \
2806 lval = (__typeof__(lval)) _res; \
2807 } while (0)
2808
2809#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2810 arg7,arg8,arg9,arg10,arg11) \
2811 do { \
2812 volatile OrigFn _orig = (orig); \
2813 volatile unsigned long _argvec[3+11]; \
2814 volatile unsigned long _res; \
2815 /* _argvec[0] holds current r2 across the call */ \
2816 _argvec[1] = (unsigned long)_orig.r2; \
2817 _argvec[2] = (unsigned long)_orig.nraddr; \
2818 _argvec[2+1] = (unsigned long)arg1; \
2819 _argvec[2+2] = (unsigned long)arg2; \
2820 _argvec[2+3] = (unsigned long)arg3; \
2821 _argvec[2+4] = (unsigned long)arg4; \
2822 _argvec[2+5] = (unsigned long)arg5; \
2823 _argvec[2+6] = (unsigned long)arg6; \
2824 _argvec[2+7] = (unsigned long)arg7; \
2825 _argvec[2+8] = (unsigned long)arg8; \
2826 _argvec[2+9] = (unsigned long)arg9; \
2827 _argvec[2+10] = (unsigned long)arg10; \
2828 _argvec[2+11] = (unsigned long)arg11; \
2829 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002830 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002831 "mr 11,%1\n\t" \
2832 "std 2,-16(11)\n\t" /* save tocptr */ \
2833 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2834 "addi 1,1,-144\n\t" /* expand stack frame */ \
2835 /* arg11 */ \
2836 "ld 3,88(11)\n\t" \
2837 "std 3,128(1)\n\t" \
2838 /* arg10 */ \
2839 "ld 3,80(11)\n\t" \
2840 "std 3,120(1)\n\t" \
2841 /* arg9 */ \
2842 "ld 3,72(11)\n\t" \
2843 "std 3,112(1)\n\t" \
2844 /* args1-8 */ \
2845 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2846 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2847 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2848 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2849 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2850 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2851 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2852 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2853 "ld 11, 0(11)\n\t" /* target->r11 */ \
2854 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2855 "mr 11,%1\n\t" \
2856 "mr %0,3\n\t" \
2857 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00002858 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002859 : /*out*/ "=r" (_res) \
2860 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002861 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002862 ); \
2863 lval = (__typeof__(lval)) _res; \
2864 } while (0)
2865
2866#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2867 arg7,arg8,arg9,arg10,arg11,arg12) \
2868 do { \
2869 volatile OrigFn _orig = (orig); \
2870 volatile unsigned long _argvec[3+12]; \
2871 volatile unsigned long _res; \
2872 /* _argvec[0] holds current r2 across the call */ \
2873 _argvec[1] = (unsigned long)_orig.r2; \
2874 _argvec[2] = (unsigned long)_orig.nraddr; \
2875 _argvec[2+1] = (unsigned long)arg1; \
2876 _argvec[2+2] = (unsigned long)arg2; \
2877 _argvec[2+3] = (unsigned long)arg3; \
2878 _argvec[2+4] = (unsigned long)arg4; \
2879 _argvec[2+5] = (unsigned long)arg5; \
2880 _argvec[2+6] = (unsigned long)arg6; \
2881 _argvec[2+7] = (unsigned long)arg7; \
2882 _argvec[2+8] = (unsigned long)arg8; \
2883 _argvec[2+9] = (unsigned long)arg9; \
2884 _argvec[2+10] = (unsigned long)arg10; \
2885 _argvec[2+11] = (unsigned long)arg11; \
2886 _argvec[2+12] = (unsigned long)arg12; \
2887 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002888 VALGRIND_ALIGN_STACK \
sewardjcd636392006-03-12 16:48:14 +00002889 "mr 11,%1\n\t" \
2890 "std 2,-16(11)\n\t" /* save tocptr */ \
2891 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2892 "addi 1,1,-144\n\t" /* expand stack frame */ \
2893 /* arg12 */ \
2894 "ld 3,96(11)\n\t" \
2895 "std 3,136(1)\n\t" \
2896 /* arg11 */ \
2897 "ld 3,88(11)\n\t" \
2898 "std 3,128(1)\n\t" \
2899 /* arg10 */ \
2900 "ld 3,80(11)\n\t" \
2901 "std 3,120(1)\n\t" \
2902 /* arg9 */ \
2903 "ld 3,72(11)\n\t" \
2904 "std 3,112(1)\n\t" \
2905 /* args1-8 */ \
2906 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2907 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2908 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2909 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2910 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2911 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2912 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2913 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2914 "ld 11, 0(11)\n\t" /* target->r11 */ \
2915 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2916 "mr 11,%1\n\t" \
2917 "mr %0,3\n\t" \
2918 "ld 2,-16(11)\n\t" /* restore tocptr */ \
tom4118e0f2012-08-02 09:23:45 +00002919 VALGRIND_RESTORE_STACK \
sewardjcd636392006-03-12 16:48:14 +00002920 : /*out*/ "=r" (_res) \
2921 : /*in*/ "r" (&_argvec[2]) \
tom4118e0f2012-08-02 09:23:45 +00002922 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
sewardjcd636392006-03-12 16:48:14 +00002923 ); \
2924 lval = (__typeof__(lval)) _res; \
2925 } while (0)
2926
sewardjf5c1a7f2006-10-17 01:32:48 +00002927#endif /* PLAT_ppc64_linux */
2928
sewardj59570ff2010-01-01 11:59:33 +00002929/* ------------------------- arm-linux ------------------------- */
2930
2931#if defined(PLAT_arm_linux)
2932
2933/* These regs are trashed by the hidden call. */
2934#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
2935
tom4118e0f2012-08-02 09:23:45 +00002936/* Macros to save and align the stack before making a function
2937 call and restore it afterwards as gcc may not keep the stack
2938 pointer aligned if it doesn't realise calls are being made
2939 to other functions. */
2940
sewardj567e5bb2012-08-04 19:23:54 +00002941/* This is a bit tricky. We store the original stack pointer in r10
2942 as it is callee-saves. gcc doesn't allow the use of r11 for some
2943 reason. Also, we can't directly "bic" the stack pointer in thumb
2944 mode since r13 isn't an allowed register number in that context.
2945 So use r4 as a temporary, since that is about to get trashed
2946 anyway, just after each use of this macro. Side effect is we need
2947 to be very careful about any future changes, since
2948 VALGRIND_ALIGN_STACK simply assumes r4 is usable. */
tom4118e0f2012-08-02 09:23:45 +00002949#define VALGRIND_ALIGN_STACK \
sewardj567e5bb2012-08-04 19:23:54 +00002950 "mov r10, sp\n\t" \
2951 "mov r4, sp\n\t" \
2952 "bic r4, r4, #7\n\t" \
2953 "mov sp, r4\n\t"
tom4118e0f2012-08-02 09:23:45 +00002954#define VALGRIND_RESTORE_STACK \
sewardj567e5bb2012-08-04 19:23:54 +00002955 "mov sp, r10\n\t"
tom4118e0f2012-08-02 09:23:45 +00002956
sewardj59570ff2010-01-01 11:59:33 +00002957/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
2958 long) == 4. */
2959
2960#define CALL_FN_W_v(lval, orig) \
2961 do { \
2962 volatile OrigFn _orig = (orig); \
2963 volatile unsigned long _argvec[1]; \
2964 volatile unsigned long _res; \
2965 _argvec[0] = (unsigned long)_orig.nraddr; \
2966 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002967 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00002968 "ldr r4, [%1] \n\t" /* target->r4 */ \
2969 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00002970 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00002971 "mov %0, r0\n" \
2972 : /*out*/ "=r" (_res) \
2973 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00002974 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00002975 ); \
2976 lval = (__typeof__(lval)) _res; \
2977 } while (0)
2978
2979#define CALL_FN_W_W(lval, orig, arg1) \
2980 do { \
2981 volatile OrigFn _orig = (orig); \
2982 volatile unsigned long _argvec[2]; \
2983 volatile unsigned long _res; \
2984 _argvec[0] = (unsigned long)_orig.nraddr; \
2985 _argvec[1] = (unsigned long)(arg1); \
2986 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00002987 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00002988 "ldr r0, [%1, #4] \n\t" \
2989 "ldr r4, [%1] \n\t" /* target->r4 */ \
2990 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00002991 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00002992 "mov %0, r0\n" \
2993 : /*out*/ "=r" (_res) \
2994 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00002995 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00002996 ); \
2997 lval = (__typeof__(lval)) _res; \
2998 } while (0)
2999
3000#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3001 do { \
3002 volatile OrigFn _orig = (orig); \
3003 volatile unsigned long _argvec[3]; \
3004 volatile unsigned long _res; \
3005 _argvec[0] = (unsigned long)_orig.nraddr; \
3006 _argvec[1] = (unsigned long)(arg1); \
3007 _argvec[2] = (unsigned long)(arg2); \
3008 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003009 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003010 "ldr r0, [%1, #4] \n\t" \
3011 "ldr r1, [%1, #8] \n\t" \
3012 "ldr r4, [%1] \n\t" /* target->r4 */ \
3013 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003014 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003015 "mov %0, r0\n" \
3016 : /*out*/ "=r" (_res) \
3017 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003018 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003019 ); \
3020 lval = (__typeof__(lval)) _res; \
3021 } while (0)
3022
3023#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3024 do { \
3025 volatile OrigFn _orig = (orig); \
3026 volatile unsigned long _argvec[4]; \
3027 volatile unsigned long _res; \
3028 _argvec[0] = (unsigned long)_orig.nraddr; \
3029 _argvec[1] = (unsigned long)(arg1); \
3030 _argvec[2] = (unsigned long)(arg2); \
3031 _argvec[3] = (unsigned long)(arg3); \
3032 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003033 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003034 "ldr r0, [%1, #4] \n\t" \
3035 "ldr r1, [%1, #8] \n\t" \
3036 "ldr r2, [%1, #12] \n\t" \
3037 "ldr r4, [%1] \n\t" /* target->r4 */ \
3038 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003039 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003040 "mov %0, r0\n" \
3041 : /*out*/ "=r" (_res) \
3042 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003043 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003044 ); \
3045 lval = (__typeof__(lval)) _res; \
3046 } while (0)
3047
3048#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3049 do { \
3050 volatile OrigFn _orig = (orig); \
3051 volatile unsigned long _argvec[5]; \
3052 volatile unsigned long _res; \
3053 _argvec[0] = (unsigned long)_orig.nraddr; \
3054 _argvec[1] = (unsigned long)(arg1); \
3055 _argvec[2] = (unsigned long)(arg2); \
3056 _argvec[3] = (unsigned long)(arg3); \
3057 _argvec[4] = (unsigned long)(arg4); \
3058 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003059 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003060 "ldr r0, [%1, #4] \n\t" \
3061 "ldr r1, [%1, #8] \n\t" \
3062 "ldr r2, [%1, #12] \n\t" \
3063 "ldr r3, [%1, #16] \n\t" \
3064 "ldr r4, [%1] \n\t" /* target->r4 */ \
3065 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003066 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003067 "mov %0, r0" \
3068 : /*out*/ "=r" (_res) \
3069 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003070 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003071 ); \
3072 lval = (__typeof__(lval)) _res; \
3073 } while (0)
3074
3075#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3076 do { \
3077 volatile OrigFn _orig = (orig); \
3078 volatile unsigned long _argvec[6]; \
3079 volatile unsigned long _res; \
3080 _argvec[0] = (unsigned long)_orig.nraddr; \
3081 _argvec[1] = (unsigned long)(arg1); \
3082 _argvec[2] = (unsigned long)(arg2); \
3083 _argvec[3] = (unsigned long)(arg3); \
3084 _argvec[4] = (unsigned long)(arg4); \
3085 _argvec[5] = (unsigned long)(arg5); \
3086 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003087 VALGRIND_ALIGN_STACK \
3088 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003089 "ldr r0, [%1, #20] \n\t" \
3090 "push {r0} \n\t" \
3091 "ldr r0, [%1, #4] \n\t" \
3092 "ldr r1, [%1, #8] \n\t" \
3093 "ldr r2, [%1, #12] \n\t" \
3094 "ldr r3, [%1, #16] \n\t" \
3095 "ldr r4, [%1] \n\t" /* target->r4 */ \
3096 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003097 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003098 "mov %0, r0" \
3099 : /*out*/ "=r" (_res) \
3100 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003101 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003102 ); \
3103 lval = (__typeof__(lval)) _res; \
3104 } while (0)
3105
3106#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3107 do { \
3108 volatile OrigFn _orig = (orig); \
3109 volatile unsigned long _argvec[7]; \
3110 volatile unsigned long _res; \
3111 _argvec[0] = (unsigned long)_orig.nraddr; \
3112 _argvec[1] = (unsigned long)(arg1); \
3113 _argvec[2] = (unsigned long)(arg2); \
3114 _argvec[3] = (unsigned long)(arg3); \
3115 _argvec[4] = (unsigned long)(arg4); \
3116 _argvec[5] = (unsigned long)(arg5); \
3117 _argvec[6] = (unsigned long)(arg6); \
3118 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003119 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003120 "ldr r0, [%1, #20] \n\t" \
3121 "ldr r1, [%1, #24] \n\t" \
3122 "push {r0, r1} \n\t" \
3123 "ldr r0, [%1, #4] \n\t" \
3124 "ldr r1, [%1, #8] \n\t" \
3125 "ldr r2, [%1, #12] \n\t" \
3126 "ldr r3, [%1, #16] \n\t" \
3127 "ldr r4, [%1] \n\t" /* target->r4 */ \
3128 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003129 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003130 "mov %0, r0" \
3131 : /*out*/ "=r" (_res) \
3132 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003133 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003134 ); \
3135 lval = (__typeof__(lval)) _res; \
3136 } while (0)
3137
3138#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3139 arg7) \
3140 do { \
3141 volatile OrigFn _orig = (orig); \
3142 volatile unsigned long _argvec[8]; \
3143 volatile unsigned long _res; \
3144 _argvec[0] = (unsigned long)_orig.nraddr; \
3145 _argvec[1] = (unsigned long)(arg1); \
3146 _argvec[2] = (unsigned long)(arg2); \
3147 _argvec[3] = (unsigned long)(arg3); \
3148 _argvec[4] = (unsigned long)(arg4); \
3149 _argvec[5] = (unsigned long)(arg5); \
3150 _argvec[6] = (unsigned long)(arg6); \
3151 _argvec[7] = (unsigned long)(arg7); \
3152 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003153 VALGRIND_ALIGN_STACK \
3154 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003155 "ldr r0, [%1, #20] \n\t" \
3156 "ldr r1, [%1, #24] \n\t" \
3157 "ldr r2, [%1, #28] \n\t" \
3158 "push {r0, r1, r2} \n\t" \
3159 "ldr r0, [%1, #4] \n\t" \
3160 "ldr r1, [%1, #8] \n\t" \
3161 "ldr r2, [%1, #12] \n\t" \
3162 "ldr r3, [%1, #16] \n\t" \
3163 "ldr r4, [%1] \n\t" /* target->r4 */ \
3164 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003165 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003166 "mov %0, r0" \
3167 : /*out*/ "=r" (_res) \
3168 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003169 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003170 ); \
3171 lval = (__typeof__(lval)) _res; \
3172 } while (0)
3173
3174#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3175 arg7,arg8) \
3176 do { \
3177 volatile OrigFn _orig = (orig); \
3178 volatile unsigned long _argvec[9]; \
3179 volatile unsigned long _res; \
3180 _argvec[0] = (unsigned long)_orig.nraddr; \
3181 _argvec[1] = (unsigned long)(arg1); \
3182 _argvec[2] = (unsigned long)(arg2); \
3183 _argvec[3] = (unsigned long)(arg3); \
3184 _argvec[4] = (unsigned long)(arg4); \
3185 _argvec[5] = (unsigned long)(arg5); \
3186 _argvec[6] = (unsigned long)(arg6); \
3187 _argvec[7] = (unsigned long)(arg7); \
3188 _argvec[8] = (unsigned long)(arg8); \
3189 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003190 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003191 "ldr r0, [%1, #20] \n\t" \
3192 "ldr r1, [%1, #24] \n\t" \
3193 "ldr r2, [%1, #28] \n\t" \
3194 "ldr r3, [%1, #32] \n\t" \
3195 "push {r0, r1, r2, r3} \n\t" \
3196 "ldr r0, [%1, #4] \n\t" \
3197 "ldr r1, [%1, #8] \n\t" \
3198 "ldr r2, [%1, #12] \n\t" \
3199 "ldr r3, [%1, #16] \n\t" \
3200 "ldr r4, [%1] \n\t" /* target->r4 */ \
3201 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003202 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003203 "mov %0, r0" \
3204 : /*out*/ "=r" (_res) \
3205 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003206 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003207 ); \
3208 lval = (__typeof__(lval)) _res; \
3209 } while (0)
3210
3211#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3212 arg7,arg8,arg9) \
3213 do { \
3214 volatile OrigFn _orig = (orig); \
3215 volatile unsigned long _argvec[10]; \
3216 volatile unsigned long _res; \
3217 _argvec[0] = (unsigned long)_orig.nraddr; \
3218 _argvec[1] = (unsigned long)(arg1); \
3219 _argvec[2] = (unsigned long)(arg2); \
3220 _argvec[3] = (unsigned long)(arg3); \
3221 _argvec[4] = (unsigned long)(arg4); \
3222 _argvec[5] = (unsigned long)(arg5); \
3223 _argvec[6] = (unsigned long)(arg6); \
3224 _argvec[7] = (unsigned long)(arg7); \
3225 _argvec[8] = (unsigned long)(arg8); \
3226 _argvec[9] = (unsigned long)(arg9); \
3227 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003228 VALGRIND_ALIGN_STACK \
3229 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003230 "ldr r0, [%1, #20] \n\t" \
3231 "ldr r1, [%1, #24] \n\t" \
3232 "ldr r2, [%1, #28] \n\t" \
3233 "ldr r3, [%1, #32] \n\t" \
3234 "ldr r4, [%1, #36] \n\t" \
3235 "push {r0, r1, r2, r3, r4} \n\t" \
3236 "ldr r0, [%1, #4] \n\t" \
3237 "ldr r1, [%1, #8] \n\t" \
3238 "ldr r2, [%1, #12] \n\t" \
3239 "ldr r3, [%1, #16] \n\t" \
3240 "ldr r4, [%1] \n\t" /* target->r4 */ \
3241 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003242 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003243 "mov %0, r0" \
3244 : /*out*/ "=r" (_res) \
3245 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003246 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003247 ); \
3248 lval = (__typeof__(lval)) _res; \
3249 } while (0)
3250
3251#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3252 arg7,arg8,arg9,arg10) \
3253 do { \
3254 volatile OrigFn _orig = (orig); \
3255 volatile unsigned long _argvec[11]; \
3256 volatile unsigned long _res; \
3257 _argvec[0] = (unsigned long)_orig.nraddr; \
3258 _argvec[1] = (unsigned long)(arg1); \
3259 _argvec[2] = (unsigned long)(arg2); \
3260 _argvec[3] = (unsigned long)(arg3); \
3261 _argvec[4] = (unsigned long)(arg4); \
3262 _argvec[5] = (unsigned long)(arg5); \
3263 _argvec[6] = (unsigned long)(arg6); \
3264 _argvec[7] = (unsigned long)(arg7); \
3265 _argvec[8] = (unsigned long)(arg8); \
3266 _argvec[9] = (unsigned long)(arg9); \
3267 _argvec[10] = (unsigned long)(arg10); \
3268 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003269 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003270 "ldr r0, [%1, #40] \n\t" \
3271 "push {r0} \n\t" \
3272 "ldr r0, [%1, #20] \n\t" \
3273 "ldr r1, [%1, #24] \n\t" \
3274 "ldr r2, [%1, #28] \n\t" \
3275 "ldr r3, [%1, #32] \n\t" \
3276 "ldr r4, [%1, #36] \n\t" \
3277 "push {r0, r1, r2, r3, r4} \n\t" \
3278 "ldr r0, [%1, #4] \n\t" \
3279 "ldr r1, [%1, #8] \n\t" \
3280 "ldr r2, [%1, #12] \n\t" \
3281 "ldr r3, [%1, #16] \n\t" \
3282 "ldr r4, [%1] \n\t" /* target->r4 */ \
3283 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003284 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003285 "mov %0, r0" \
3286 : /*out*/ "=r" (_res) \
3287 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003288 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003289 ); \
3290 lval = (__typeof__(lval)) _res; \
3291 } while (0)
3292
3293#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3294 arg6,arg7,arg8,arg9,arg10, \
3295 arg11) \
3296 do { \
3297 volatile OrigFn _orig = (orig); \
3298 volatile unsigned long _argvec[12]; \
3299 volatile unsigned long _res; \
3300 _argvec[0] = (unsigned long)_orig.nraddr; \
3301 _argvec[1] = (unsigned long)(arg1); \
3302 _argvec[2] = (unsigned long)(arg2); \
3303 _argvec[3] = (unsigned long)(arg3); \
3304 _argvec[4] = (unsigned long)(arg4); \
3305 _argvec[5] = (unsigned long)(arg5); \
3306 _argvec[6] = (unsigned long)(arg6); \
3307 _argvec[7] = (unsigned long)(arg7); \
3308 _argvec[8] = (unsigned long)(arg8); \
3309 _argvec[9] = (unsigned long)(arg9); \
3310 _argvec[10] = (unsigned long)(arg10); \
3311 _argvec[11] = (unsigned long)(arg11); \
3312 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003313 VALGRIND_ALIGN_STACK \
3314 "sub sp, sp, #4 \n\t" \
sewardj59570ff2010-01-01 11:59:33 +00003315 "ldr r0, [%1, #40] \n\t" \
3316 "ldr r1, [%1, #44] \n\t" \
3317 "push {r0, r1} \n\t" \
3318 "ldr r0, [%1, #20] \n\t" \
3319 "ldr r1, [%1, #24] \n\t" \
3320 "ldr r2, [%1, #28] \n\t" \
3321 "ldr r3, [%1, #32] \n\t" \
3322 "ldr r4, [%1, #36] \n\t" \
3323 "push {r0, r1, r2, r3, r4} \n\t" \
3324 "ldr r0, [%1, #4] \n\t" \
3325 "ldr r1, [%1, #8] \n\t" \
3326 "ldr r2, [%1, #12] \n\t" \
3327 "ldr r3, [%1, #16] \n\t" \
3328 "ldr r4, [%1] \n\t" /* target->r4 */ \
3329 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003330 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003331 "mov %0, r0" \
3332 : /*out*/ "=r" (_res) \
3333 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003334 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003335 ); \
3336 lval = (__typeof__(lval)) _res; \
3337 } while (0)
3338
3339#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3340 arg6,arg7,arg8,arg9,arg10, \
3341 arg11,arg12) \
3342 do { \
3343 volatile OrigFn _orig = (orig); \
3344 volatile unsigned long _argvec[13]; \
3345 volatile unsigned long _res; \
3346 _argvec[0] = (unsigned long)_orig.nraddr; \
3347 _argvec[1] = (unsigned long)(arg1); \
3348 _argvec[2] = (unsigned long)(arg2); \
3349 _argvec[3] = (unsigned long)(arg3); \
3350 _argvec[4] = (unsigned long)(arg4); \
3351 _argvec[5] = (unsigned long)(arg5); \
3352 _argvec[6] = (unsigned long)(arg6); \
3353 _argvec[7] = (unsigned long)(arg7); \
3354 _argvec[8] = (unsigned long)(arg8); \
3355 _argvec[9] = (unsigned long)(arg9); \
3356 _argvec[10] = (unsigned long)(arg10); \
3357 _argvec[11] = (unsigned long)(arg11); \
3358 _argvec[12] = (unsigned long)(arg12); \
3359 __asm__ volatile( \
tom4118e0f2012-08-02 09:23:45 +00003360 VALGRIND_ALIGN_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003361 "ldr r0, [%1, #40] \n\t" \
3362 "ldr r1, [%1, #44] \n\t" \
3363 "ldr r2, [%1, #48] \n\t" \
3364 "push {r0, r1, r2} \n\t" \
3365 "ldr r0, [%1, #20] \n\t" \
3366 "ldr r1, [%1, #24] \n\t" \
3367 "ldr r2, [%1, #28] \n\t" \
3368 "ldr r3, [%1, #32] \n\t" \
3369 "ldr r4, [%1, #36] \n\t" \
3370 "push {r0, r1, r2, r3, r4} \n\t" \
3371 "ldr r0, [%1, #4] \n\t" \
3372 "ldr r1, [%1, #8] \n\t" \
3373 "ldr r2, [%1, #12] \n\t" \
3374 "ldr r3, [%1, #16] \n\t" \
3375 "ldr r4, [%1] \n\t" /* target->r4 */ \
3376 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
tom4118e0f2012-08-02 09:23:45 +00003377 VALGRIND_RESTORE_STACK \
sewardj59570ff2010-01-01 11:59:33 +00003378 "mov %0, r0" \
3379 : /*out*/ "=r" (_res) \
3380 : /*in*/ "0" (&_argvec[0]) \
sewardj567e5bb2012-08-04 19:23:54 +00003381 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
sewardj59570ff2010-01-01 11:59:33 +00003382 ); \
3383 lval = (__typeof__(lval)) _res; \
3384 } while (0)
3385
3386#endif /* PLAT_arm_linux */
3387
sewardjb5b87402011-03-07 16:05:35 +00003388/* ------------------------- s390x-linux ------------------------- */
3389
3390#if defined(PLAT_s390x_linux)
3391
3392/* Similar workaround as amd64 (see above), but we use r11 as frame
3393 pointer and save the old r11 in r7. r11 might be used for
3394 argvec, therefore we copy argvec in r1 since r1 is clobbered
3395 after the call anyway. */
3396#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
3397# define __FRAME_POINTER \
3398 ,"d"(__builtin_dwarf_cfa())
3399# define VALGRIND_CFI_PROLOGUE \
3400 ".cfi_remember_state\n\t" \
3401 "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */ \
3402 "lgr 7,11\n\t" \
3403 "lgr 11,%2\n\t" \
3404 ".cfi_def_cfa r11, 0\n\t"
3405# define VALGRIND_CFI_EPILOGUE \
3406 "lgr 11, 7\n\t" \
3407 ".cfi_restore_state\n\t"
3408#else
3409# define __FRAME_POINTER
3410# define VALGRIND_CFI_PROLOGUE \
3411 "lgr 1,%1\n\t"
3412# define VALGRIND_CFI_EPILOGUE
3413#endif
3414
florian9af940f2012-08-03 03:21:42 +00003415/* Nb: On s390 the stack pointer is properly aligned *at all times*
3416 according to the s390 GCC maintainer. (The ABI specification is not
3417 precise in this regard.) Therefore, VALGRIND_ALIGN_STACK and
3418 VALGRIND_RESTORE_STACK are not defined here. */
sewardjb5b87402011-03-07 16:05:35 +00003419
3420/* These regs are trashed by the hidden call. Note that we overwrite
3421 r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
3422 function a proper return address. All others are ABI defined call
3423 clobbers. */
3424#define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \
3425 "f0","f1","f2","f3","f4","f5","f6","f7"
3426
florian9af940f2012-08-03 03:21:42 +00003427/* Nb: Although r11 is modified in the asm snippets below (inside
3428 VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for
3429 two reasons:
3430 (1) r11 is restored in VALGRIND_CFI_EPILOGUE, so effectively it is not
3431 modified
3432 (2) GCC will complain that r11 cannot appear inside a clobber section,
3433 when compiled with -O -fno-omit-frame-pointer
3434 */
sewardjb5b87402011-03-07 16:05:35 +00003435
3436#define CALL_FN_W_v(lval, orig) \
3437 do { \
3438 volatile OrigFn _orig = (orig); \
3439 volatile unsigned long _argvec[1]; \
3440 volatile unsigned long _res; \
3441 _argvec[0] = (unsigned long)_orig.nraddr; \
3442 __asm__ volatile( \
3443 VALGRIND_CFI_PROLOGUE \
3444 "aghi 15,-160\n\t" \
3445 "lg 1, 0(1)\n\t" /* target->r1 */ \
3446 VALGRIND_CALL_NOREDIR_R1 \
3447 "lgr %0, 2\n\t" \
3448 "aghi 15,160\n\t" \
3449 VALGRIND_CFI_EPILOGUE \
3450 : /*out*/ "=d" (_res) \
3451 : /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \
3452 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3453 ); \
3454 lval = (__typeof__(lval)) _res; \
3455 } while (0)
3456
3457/* The call abi has the arguments in r2-r6 and stack */
3458#define CALL_FN_W_W(lval, orig, arg1) \
3459 do { \
3460 volatile OrigFn _orig = (orig); \
3461 volatile unsigned long _argvec[2]; \
3462 volatile unsigned long _res; \
3463 _argvec[0] = (unsigned long)_orig.nraddr; \
3464 _argvec[1] = (unsigned long)arg1; \
3465 __asm__ volatile( \
3466 VALGRIND_CFI_PROLOGUE \
3467 "aghi 15,-160\n\t" \
3468 "lg 2, 8(1)\n\t" \
3469 "lg 1, 0(1)\n\t" \
3470 VALGRIND_CALL_NOREDIR_R1 \
3471 "lgr %0, 2\n\t" \
3472 "aghi 15,160\n\t" \
3473 VALGRIND_CFI_EPILOGUE \
3474 : /*out*/ "=d" (_res) \
3475 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3476 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3477 ); \
3478 lval = (__typeof__(lval)) _res; \
3479 } while (0)
3480
3481#define CALL_FN_W_WW(lval, orig, arg1, arg2) \
3482 do { \
3483 volatile OrigFn _orig = (orig); \
3484 volatile unsigned long _argvec[3]; \
3485 volatile unsigned long _res; \
3486 _argvec[0] = (unsigned long)_orig.nraddr; \
3487 _argvec[1] = (unsigned long)arg1; \
3488 _argvec[2] = (unsigned long)arg2; \
3489 __asm__ volatile( \
3490 VALGRIND_CFI_PROLOGUE \
3491 "aghi 15,-160\n\t" \
3492 "lg 2, 8(1)\n\t" \
3493 "lg 3,16(1)\n\t" \
3494 "lg 1, 0(1)\n\t" \
3495 VALGRIND_CALL_NOREDIR_R1 \
3496 "lgr %0, 2\n\t" \
3497 "aghi 15,160\n\t" \
3498 VALGRIND_CFI_EPILOGUE \
3499 : /*out*/ "=d" (_res) \
3500 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3501 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3502 ); \
3503 lval = (__typeof__(lval)) _res; \
3504 } while (0)
3505
3506#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \
3507 do { \
3508 volatile OrigFn _orig = (orig); \
3509 volatile unsigned long _argvec[4]; \
3510 volatile unsigned long _res; \
3511 _argvec[0] = (unsigned long)_orig.nraddr; \
3512 _argvec[1] = (unsigned long)arg1; \
3513 _argvec[2] = (unsigned long)arg2; \
3514 _argvec[3] = (unsigned long)arg3; \
3515 __asm__ volatile( \
3516 VALGRIND_CFI_PROLOGUE \
3517 "aghi 15,-160\n\t" \
3518 "lg 2, 8(1)\n\t" \
3519 "lg 3,16(1)\n\t" \
3520 "lg 4,24(1)\n\t" \
3521 "lg 1, 0(1)\n\t" \
3522 VALGRIND_CALL_NOREDIR_R1 \
3523 "lgr %0, 2\n\t" \
3524 "aghi 15,160\n\t" \
3525 VALGRIND_CFI_EPILOGUE \
3526 : /*out*/ "=d" (_res) \
3527 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3528 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3529 ); \
3530 lval = (__typeof__(lval)) _res; \
3531 } while (0)
3532
3533#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \
3534 do { \
3535 volatile OrigFn _orig = (orig); \
3536 volatile unsigned long _argvec[5]; \
3537 volatile unsigned long _res; \
3538 _argvec[0] = (unsigned long)_orig.nraddr; \
3539 _argvec[1] = (unsigned long)arg1; \
3540 _argvec[2] = (unsigned long)arg2; \
3541 _argvec[3] = (unsigned long)arg3; \
3542 _argvec[4] = (unsigned long)arg4; \
3543 __asm__ volatile( \
3544 VALGRIND_CFI_PROLOGUE \
3545 "aghi 15,-160\n\t" \
3546 "lg 2, 8(1)\n\t" \
3547 "lg 3,16(1)\n\t" \
3548 "lg 4,24(1)\n\t" \
3549 "lg 5,32(1)\n\t" \
3550 "lg 1, 0(1)\n\t" \
3551 VALGRIND_CALL_NOREDIR_R1 \
3552 "lgr %0, 2\n\t" \
3553 "aghi 15,160\n\t" \
3554 VALGRIND_CFI_EPILOGUE \
3555 : /*out*/ "=d" (_res) \
3556 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3557 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
3558 ); \
3559 lval = (__typeof__(lval)) _res; \
3560 } while (0)
3561
3562#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \
3563 do { \
3564 volatile OrigFn _orig = (orig); \
3565 volatile unsigned long _argvec[6]; \
3566 volatile unsigned long _res; \
3567 _argvec[0] = (unsigned long)_orig.nraddr; \
3568 _argvec[1] = (unsigned long)arg1; \
3569 _argvec[2] = (unsigned long)arg2; \
3570 _argvec[3] = (unsigned long)arg3; \
3571 _argvec[4] = (unsigned long)arg4; \
3572 _argvec[5] = (unsigned long)arg5; \
3573 __asm__ volatile( \
3574 VALGRIND_CFI_PROLOGUE \
3575 "aghi 15,-160\n\t" \
3576 "lg 2, 8(1)\n\t" \
3577 "lg 3,16(1)\n\t" \
3578 "lg 4,24(1)\n\t" \
3579 "lg 5,32(1)\n\t" \
3580 "lg 6,40(1)\n\t" \
3581 "lg 1, 0(1)\n\t" \
3582 VALGRIND_CALL_NOREDIR_R1 \
3583 "lgr %0, 2\n\t" \
3584 "aghi 15,160\n\t" \
3585 VALGRIND_CFI_EPILOGUE \
3586 : /*out*/ "=d" (_res) \
3587 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3588 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3589 ); \
3590 lval = (__typeof__(lval)) _res; \
3591 } while (0)
3592
3593#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3594 arg6) \
3595 do { \
3596 volatile OrigFn _orig = (orig); \
3597 volatile unsigned long _argvec[7]; \
3598 volatile unsigned long _res; \
3599 _argvec[0] = (unsigned long)_orig.nraddr; \
3600 _argvec[1] = (unsigned long)arg1; \
3601 _argvec[2] = (unsigned long)arg2; \
3602 _argvec[3] = (unsigned long)arg3; \
3603 _argvec[4] = (unsigned long)arg4; \
3604 _argvec[5] = (unsigned long)arg5; \
3605 _argvec[6] = (unsigned long)arg6; \
3606 __asm__ volatile( \
3607 VALGRIND_CFI_PROLOGUE \
3608 "aghi 15,-168\n\t" \
3609 "lg 2, 8(1)\n\t" \
3610 "lg 3,16(1)\n\t" \
3611 "lg 4,24(1)\n\t" \
3612 "lg 5,32(1)\n\t" \
3613 "lg 6,40(1)\n\t" \
3614 "mvc 160(8,15), 48(1)\n\t" \
3615 "lg 1, 0(1)\n\t" \
3616 VALGRIND_CALL_NOREDIR_R1 \
3617 "lgr %0, 2\n\t" \
3618 "aghi 15,168\n\t" \
3619 VALGRIND_CFI_EPILOGUE \
3620 : /*out*/ "=d" (_res) \
3621 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3622 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3623 ); \
3624 lval = (__typeof__(lval)) _res; \
3625 } while (0)
3626
3627#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3628 arg6, arg7) \
3629 do { \
3630 volatile OrigFn _orig = (orig); \
3631 volatile unsigned long _argvec[8]; \
3632 volatile unsigned long _res; \
3633 _argvec[0] = (unsigned long)_orig.nraddr; \
3634 _argvec[1] = (unsigned long)arg1; \
3635 _argvec[2] = (unsigned long)arg2; \
3636 _argvec[3] = (unsigned long)arg3; \
3637 _argvec[4] = (unsigned long)arg4; \
3638 _argvec[5] = (unsigned long)arg5; \
3639 _argvec[6] = (unsigned long)arg6; \
3640 _argvec[7] = (unsigned long)arg7; \
3641 __asm__ volatile( \
3642 VALGRIND_CFI_PROLOGUE \
3643 "aghi 15,-176\n\t" \
3644 "lg 2, 8(1)\n\t" \
3645 "lg 3,16(1)\n\t" \
3646 "lg 4,24(1)\n\t" \
3647 "lg 5,32(1)\n\t" \
3648 "lg 6,40(1)\n\t" \
3649 "mvc 160(8,15), 48(1)\n\t" \
3650 "mvc 168(8,15), 56(1)\n\t" \
3651 "lg 1, 0(1)\n\t" \
3652 VALGRIND_CALL_NOREDIR_R1 \
3653 "lgr %0, 2\n\t" \
3654 "aghi 15,176\n\t" \
3655 VALGRIND_CFI_EPILOGUE \
3656 : /*out*/ "=d" (_res) \
3657 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3658 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3659 ); \
3660 lval = (__typeof__(lval)) _res; \
3661 } while (0)
3662
3663#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3664 arg6, arg7 ,arg8) \
3665 do { \
3666 volatile OrigFn _orig = (orig); \
3667 volatile unsigned long _argvec[9]; \
3668 volatile unsigned long _res; \
3669 _argvec[0] = (unsigned long)_orig.nraddr; \
3670 _argvec[1] = (unsigned long)arg1; \
3671 _argvec[2] = (unsigned long)arg2; \
3672 _argvec[3] = (unsigned long)arg3; \
3673 _argvec[4] = (unsigned long)arg4; \
3674 _argvec[5] = (unsigned long)arg5; \
3675 _argvec[6] = (unsigned long)arg6; \
3676 _argvec[7] = (unsigned long)arg7; \
3677 _argvec[8] = (unsigned long)arg8; \
3678 __asm__ volatile( \
3679 VALGRIND_CFI_PROLOGUE \
3680 "aghi 15,-184\n\t" \
3681 "lg 2, 8(1)\n\t" \
3682 "lg 3,16(1)\n\t" \
3683 "lg 4,24(1)\n\t" \
3684 "lg 5,32(1)\n\t" \
3685 "lg 6,40(1)\n\t" \
3686 "mvc 160(8,15), 48(1)\n\t" \
3687 "mvc 168(8,15), 56(1)\n\t" \
3688 "mvc 176(8,15), 64(1)\n\t" \
3689 "lg 1, 0(1)\n\t" \
3690 VALGRIND_CALL_NOREDIR_R1 \
3691 "lgr %0, 2\n\t" \
3692 "aghi 15,184\n\t" \
3693 VALGRIND_CFI_EPILOGUE \
3694 : /*out*/ "=d" (_res) \
3695 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3696 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3697 ); \
3698 lval = (__typeof__(lval)) _res; \
3699 } while (0)
3700
3701#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3702 arg6, arg7 ,arg8, arg9) \
3703 do { \
3704 volatile OrigFn _orig = (orig); \
3705 volatile unsigned long _argvec[10]; \
3706 volatile unsigned long _res; \
3707 _argvec[0] = (unsigned long)_orig.nraddr; \
3708 _argvec[1] = (unsigned long)arg1; \
3709 _argvec[2] = (unsigned long)arg2; \
3710 _argvec[3] = (unsigned long)arg3; \
3711 _argvec[4] = (unsigned long)arg4; \
3712 _argvec[5] = (unsigned long)arg5; \
3713 _argvec[6] = (unsigned long)arg6; \
3714 _argvec[7] = (unsigned long)arg7; \
3715 _argvec[8] = (unsigned long)arg8; \
3716 _argvec[9] = (unsigned long)arg9; \
3717 __asm__ volatile( \
3718 VALGRIND_CFI_PROLOGUE \
3719 "aghi 15,-192\n\t" \
3720 "lg 2, 8(1)\n\t" \
3721 "lg 3,16(1)\n\t" \
3722 "lg 4,24(1)\n\t" \
3723 "lg 5,32(1)\n\t" \
3724 "lg 6,40(1)\n\t" \
3725 "mvc 160(8,15), 48(1)\n\t" \
3726 "mvc 168(8,15), 56(1)\n\t" \
3727 "mvc 176(8,15), 64(1)\n\t" \
3728 "mvc 184(8,15), 72(1)\n\t" \
3729 "lg 1, 0(1)\n\t" \
3730 VALGRIND_CALL_NOREDIR_R1 \
3731 "lgr %0, 2\n\t" \
3732 "aghi 15,192\n\t" \
3733 VALGRIND_CFI_EPILOGUE \
3734 : /*out*/ "=d" (_res) \
3735 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3736 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3737 ); \
3738 lval = (__typeof__(lval)) _res; \
3739 } while (0)
3740
3741#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3742 arg6, arg7 ,arg8, arg9, arg10) \
3743 do { \
3744 volatile OrigFn _orig = (orig); \
3745 volatile unsigned long _argvec[11]; \
3746 volatile unsigned long _res; \
3747 _argvec[0] = (unsigned long)_orig.nraddr; \
3748 _argvec[1] = (unsigned long)arg1; \
3749 _argvec[2] = (unsigned long)arg2; \
3750 _argvec[3] = (unsigned long)arg3; \
3751 _argvec[4] = (unsigned long)arg4; \
3752 _argvec[5] = (unsigned long)arg5; \
3753 _argvec[6] = (unsigned long)arg6; \
3754 _argvec[7] = (unsigned long)arg7; \
3755 _argvec[8] = (unsigned long)arg8; \
3756 _argvec[9] = (unsigned long)arg9; \
3757 _argvec[10] = (unsigned long)arg10; \
3758 __asm__ volatile( \
3759 VALGRIND_CFI_PROLOGUE \
3760 "aghi 15,-200\n\t" \
3761 "lg 2, 8(1)\n\t" \
3762 "lg 3,16(1)\n\t" \
3763 "lg 4,24(1)\n\t" \
3764 "lg 5,32(1)\n\t" \
3765 "lg 6,40(1)\n\t" \
3766 "mvc 160(8,15), 48(1)\n\t" \
3767 "mvc 168(8,15), 56(1)\n\t" \
3768 "mvc 176(8,15), 64(1)\n\t" \
3769 "mvc 184(8,15), 72(1)\n\t" \
3770 "mvc 192(8,15), 80(1)\n\t" \
3771 "lg 1, 0(1)\n\t" \
3772 VALGRIND_CALL_NOREDIR_R1 \
3773 "lgr %0, 2\n\t" \
3774 "aghi 15,200\n\t" \
3775 VALGRIND_CFI_EPILOGUE \
3776 : /*out*/ "=d" (_res) \
3777 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3778 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3779 ); \
3780 lval = (__typeof__(lval)) _res; \
3781 } while (0)
3782
3783#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3784 arg6, arg7 ,arg8, arg9, arg10, arg11) \
3785 do { \
3786 volatile OrigFn _orig = (orig); \
3787 volatile unsigned long _argvec[12]; \
3788 volatile unsigned long _res; \
3789 _argvec[0] = (unsigned long)_orig.nraddr; \
3790 _argvec[1] = (unsigned long)arg1; \
3791 _argvec[2] = (unsigned long)arg2; \
3792 _argvec[3] = (unsigned long)arg3; \
3793 _argvec[4] = (unsigned long)arg4; \
3794 _argvec[5] = (unsigned long)arg5; \
3795 _argvec[6] = (unsigned long)arg6; \
3796 _argvec[7] = (unsigned long)arg7; \
3797 _argvec[8] = (unsigned long)arg8; \
3798 _argvec[9] = (unsigned long)arg9; \
3799 _argvec[10] = (unsigned long)arg10; \
3800 _argvec[11] = (unsigned long)arg11; \
3801 __asm__ volatile( \
3802 VALGRIND_CFI_PROLOGUE \
3803 "aghi 15,-208\n\t" \
3804 "lg 2, 8(1)\n\t" \
3805 "lg 3,16(1)\n\t" \
3806 "lg 4,24(1)\n\t" \
3807 "lg 5,32(1)\n\t" \
3808 "lg 6,40(1)\n\t" \
3809 "mvc 160(8,15), 48(1)\n\t" \
3810 "mvc 168(8,15), 56(1)\n\t" \
3811 "mvc 176(8,15), 64(1)\n\t" \
3812 "mvc 184(8,15), 72(1)\n\t" \
3813 "mvc 192(8,15), 80(1)\n\t" \
3814 "mvc 200(8,15), 88(1)\n\t" \
3815 "lg 1, 0(1)\n\t" \
3816 VALGRIND_CALL_NOREDIR_R1 \
3817 "lgr %0, 2\n\t" \
3818 "aghi 15,208\n\t" \
3819 VALGRIND_CFI_EPILOGUE \
3820 : /*out*/ "=d" (_res) \
3821 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3822 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3823 ); \
3824 lval = (__typeof__(lval)) _res; \
3825 } while (0)
3826
3827#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
3828 arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\
3829 do { \
3830 volatile OrigFn _orig = (orig); \
3831 volatile unsigned long _argvec[13]; \
3832 volatile unsigned long _res; \
3833 _argvec[0] = (unsigned long)_orig.nraddr; \
3834 _argvec[1] = (unsigned long)arg1; \
3835 _argvec[2] = (unsigned long)arg2; \
3836 _argvec[3] = (unsigned long)arg3; \
3837 _argvec[4] = (unsigned long)arg4; \
3838 _argvec[5] = (unsigned long)arg5; \
3839 _argvec[6] = (unsigned long)arg6; \
3840 _argvec[7] = (unsigned long)arg7; \
3841 _argvec[8] = (unsigned long)arg8; \
3842 _argvec[9] = (unsigned long)arg9; \
3843 _argvec[10] = (unsigned long)arg10; \
3844 _argvec[11] = (unsigned long)arg11; \
3845 _argvec[12] = (unsigned long)arg12; \
3846 __asm__ volatile( \
3847 VALGRIND_CFI_PROLOGUE \
3848 "aghi 15,-216\n\t" \
3849 "lg 2, 8(1)\n\t" \
3850 "lg 3,16(1)\n\t" \
3851 "lg 4,24(1)\n\t" \
3852 "lg 5,32(1)\n\t" \
3853 "lg 6,40(1)\n\t" \
3854 "mvc 160(8,15), 48(1)\n\t" \
3855 "mvc 168(8,15), 56(1)\n\t" \
3856 "mvc 176(8,15), 64(1)\n\t" \
3857 "mvc 184(8,15), 72(1)\n\t" \
3858 "mvc 192(8,15), 80(1)\n\t" \
3859 "mvc 200(8,15), 88(1)\n\t" \
3860 "mvc 208(8,15), 96(1)\n\t" \
3861 "lg 1, 0(1)\n\t" \
3862 VALGRIND_CALL_NOREDIR_R1 \
3863 "lgr %0, 2\n\t" \
3864 "aghi 15,216\n\t" \
3865 VALGRIND_CFI_EPILOGUE \
3866 : /*out*/ "=d" (_res) \
3867 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
3868 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
3869 ); \
3870 lval = (__typeof__(lval)) _res; \
3871 } while (0)
3872
3873
3874#endif /* PLAT_s390x_linux */
3875
sewardj5db15402012-06-07 09:13:21 +00003876/* ------------------------- mips-linux ------------------------- */
3877
3878#if defined(PLAT_mips32_linux)
3879
3880/* These regs are trashed by the hidden call. */
3881#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \
3882"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
3883"$25", "$31"
3884
3885/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
3886 long) == 4. */
3887
3888#define CALL_FN_W_v(lval, orig) \
3889 do { \
3890 volatile OrigFn _orig = (orig); \
3891 volatile unsigned long _argvec[1]; \
3892 volatile unsigned long _res; \
3893 _argvec[0] = (unsigned long)_orig.nraddr; \
3894 __asm__ volatile( \
3895 "subu $29, $29, 8 \n\t" \
3896 "sw $gp, 0($sp) \n\t" \
3897 "sw $ra, 4($sp) \n\t" \
3898 "subu $29, $29, 16 \n\t" \
3899 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
3900 VALGRIND_CALL_NOREDIR_T9 \
3901 "addu $29, $29, 16\n\t" \
3902 "lw $gp, 0($sp) \n\t" \
3903 "lw $ra, 4($sp) \n\t" \
3904 "addu $29, $29, 8 \n\t" \
3905 "move %0, $v0\n" \
3906 : /*out*/ "=r" (_res) \
3907 : /*in*/ "0" (&_argvec[0]) \
3908 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3909 ); \
3910 lval = (__typeof__(lval)) _res; \
3911 } while (0)
3912
3913#define CALL_FN_W_W(lval, orig, arg1) \
3914 do { \
3915 volatile OrigFn _orig = (orig); \
3916 volatile unsigned long _argvec[2]; \
3917 volatile unsigned long _res; \
3918 _argvec[0] = (unsigned long)_orig.nraddr; \
3919 _argvec[1] = (unsigned long)(arg1); \
3920 __asm__ volatile( \
3921 "subu $29, $29, 8 \n\t" \
3922 "sw $gp, 0($sp) \n\t" \
3923 "sw $ra, 4($sp) \n\t" \
3924 "subu $29, $29, 16 \n\t" \
3925 "lw $a0, 4(%1) \n\t" /* arg1*/ \
3926 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
3927 VALGRIND_CALL_NOREDIR_T9 \
3928 "addu $29, $29, 16 \n\t" \
3929 "lw $gp, 0($sp) \n\t" \
3930 "lw $ra, 4($sp) \n\t" \
3931 "addu $29, $29, 8 \n\t" \
3932 "move %0, $v0\n" \
3933 : /*out*/ "=r" (_res) \
3934 : /*in*/ "0" (&_argvec[0]) \
3935 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3936 ); \
3937 lval = (__typeof__(lval)) _res; \
3938 } while (0)
3939
3940#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3941 do { \
3942 volatile OrigFn _orig = (orig); \
3943 volatile unsigned long _argvec[3]; \
3944 volatile unsigned long _res; \
3945 _argvec[0] = (unsigned long)_orig.nraddr; \
3946 _argvec[1] = (unsigned long)(arg1); \
3947 _argvec[2] = (unsigned long)(arg2); \
3948 __asm__ volatile( \
3949 "subu $29, $29, 8 \n\t" \
3950 "sw $gp, 0($sp) \n\t" \
3951 "sw $ra, 4($sp) \n\t" \
3952 "subu $29, $29, 16 \n\t" \
3953 "lw $a0, 4(%1) \n\t" \
3954 "lw $a1, 8(%1) \n\t" \
3955 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
3956 VALGRIND_CALL_NOREDIR_T9 \
3957 "addu $29, $29, 16 \n\t" \
3958 "lw $gp, 0($sp) \n\t" \
3959 "lw $ra, 4($sp) \n\t" \
3960 "addu $29, $29, 8 \n\t" \
3961 "move %0, $v0\n" \
3962 : /*out*/ "=r" (_res) \
3963 : /*in*/ "0" (&_argvec[0]) \
3964 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3965 ); \
3966 lval = (__typeof__(lval)) _res; \
3967 } while (0)
3968
3969#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3970 do { \
3971 volatile OrigFn _orig = (orig); \
3972 volatile unsigned long _argvec[4]; \
3973 volatile unsigned long _res; \
3974 _argvec[0] = (unsigned long)_orig.nraddr; \
3975 _argvec[1] = (unsigned long)(arg1); \
3976 _argvec[2] = (unsigned long)(arg2); \
3977 _argvec[3] = (unsigned long)(arg3); \
3978 __asm__ volatile( \
3979 "subu $29, $29, 8 \n\t" \
3980 "sw $gp, 0($sp) \n\t" \
3981 "sw $ra, 4($sp) \n\t" \
3982 "subu $29, $29, 16 \n\t" \
3983 "lw $a0, 4(%1) \n\t" \
3984 "lw $a1, 8(%1) \n\t" \
3985 "lw $a2, 12(%1) \n\t" \
3986 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
3987 VALGRIND_CALL_NOREDIR_T9 \
3988 "addu $29, $29, 16 \n\t" \
3989 "lw $gp, 0($sp) \n\t" \
3990 "lw $ra, 4($sp) \n\t" \
3991 "addu $29, $29, 8 \n\t" \
3992 "move %0, $v0\n" \
3993 : /*out*/ "=r" (_res) \
3994 : /*in*/ "0" (&_argvec[0]) \
3995 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3996 ); \
3997 lval = (__typeof__(lval)) _res; \
3998 } while (0)
3999
4000#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
4001 do { \
4002 volatile OrigFn _orig = (orig); \
4003 volatile unsigned long _argvec[5]; \
4004 volatile unsigned long _res; \
4005 _argvec[0] = (unsigned long)_orig.nraddr; \
4006 _argvec[1] = (unsigned long)(arg1); \
4007 _argvec[2] = (unsigned long)(arg2); \
4008 _argvec[3] = (unsigned long)(arg3); \
4009 _argvec[4] = (unsigned long)(arg4); \
4010 __asm__ volatile( \
4011 "subu $29, $29, 8 \n\t" \
4012 "sw $gp, 0($sp) \n\t" \
4013 "sw $ra, 4($sp) \n\t" \
4014 "subu $29, $29, 16 \n\t" \
4015 "lw $a0, 4(%1) \n\t" \
4016 "lw $a1, 8(%1) \n\t" \
4017 "lw $a2, 12(%1) \n\t" \
4018 "lw $a3, 16(%1) \n\t" \
4019 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
4020 VALGRIND_CALL_NOREDIR_T9 \
4021 "addu $29, $29, 16 \n\t" \
4022 "lw $gp, 0($sp) \n\t" \
4023 "lw $ra, 4($sp) \n\t" \
4024 "addu $29, $29, 8 \n\t" \
4025 "move %0, $v0\n" \
4026 : /*out*/ "=r" (_res) \
4027 : /*in*/ "0" (&_argvec[0]) \
4028 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4029 ); \
4030 lval = (__typeof__(lval)) _res; \
4031 } while (0)
4032
4033#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
4034 do { \
4035 volatile OrigFn _orig = (orig); \
4036 volatile unsigned long _argvec[6]; \
4037 volatile unsigned long _res; \
4038 _argvec[0] = (unsigned long)_orig.nraddr; \
4039 _argvec[1] = (unsigned long)(arg1); \
4040 _argvec[2] = (unsigned long)(arg2); \
4041 _argvec[3] = (unsigned long)(arg3); \
4042 _argvec[4] = (unsigned long)(arg4); \
4043 _argvec[5] = (unsigned long)(arg5); \
4044 __asm__ volatile( \
4045 "subu $29, $29, 8 \n\t" \
4046 "sw $gp, 0($sp) \n\t" \
4047 "sw $ra, 4($sp) \n\t" \
4048 "lw $a0, 20(%1) \n\t" \
4049 "subu $sp, $sp, 24\n\t" \
4050 "sw $a0, 16($sp) \n\t" \
4051 "lw $a0, 4(%1) \n\t" \
4052 "lw $a1, 8(%1) \n\t" \
4053 "lw $a2, 12(%1) \n\t" \
4054 "lw $a3, 16(%1) \n\t" \
4055 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
4056 VALGRIND_CALL_NOREDIR_T9 \
4057 "addu $29, $29, 24 \n\t" \
4058 "lw $gp, 0($sp) \n\t" \
4059 "lw $ra, 4($sp) \n\t" \
4060 "addu $sp, $sp, 8 \n\t" \
4061 "move %0, $v0\n" \
4062 : /*out*/ "=r" (_res) \
4063 : /*in*/ "0" (&_argvec[0]) \
4064 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4065 ); \
4066 lval = (__typeof__(lval)) _res; \
4067 } while (0)
4068#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
4069 do { \
4070 volatile OrigFn _orig = (orig); \
4071 volatile unsigned long _argvec[7]; \
4072 volatile unsigned long _res; \
4073 _argvec[0] = (unsigned long)_orig.nraddr; \
4074 _argvec[1] = (unsigned long)(arg1); \
4075 _argvec[2] = (unsigned long)(arg2); \
4076 _argvec[3] = (unsigned long)(arg3); \
4077 _argvec[4] = (unsigned long)(arg4); \
4078 _argvec[5] = (unsigned long)(arg5); \
4079 _argvec[6] = (unsigned long)(arg6); \
4080 __asm__ volatile( \
4081 "subu $29, $29, 8 \n\t" \
4082 "sw $gp, 0($sp) \n\t" \
4083 "sw $ra, 4($sp) \n\t" \
4084 "lw $a0, 20(%1) \n\t" \
4085 "subu $sp, $sp, 32\n\t" \
4086 "sw $a0, 16($sp) \n\t" \
4087 "lw $a0, 24(%1) \n\t" \
4088 "nop\n\t" \
4089 "sw $a0, 20($sp) \n\t" \
4090 "lw $a0, 4(%1) \n\t" \
4091 "lw $a1, 8(%1) \n\t" \
4092 "lw $a2, 12(%1) \n\t" \
4093 "lw $a3, 16(%1) \n\t" \
4094 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
4095 VALGRIND_CALL_NOREDIR_T9 \
4096 "addu $sp, $sp, 32 \n\t" \
4097 "lw $gp, 0($sp) \n\t" \
4098 "lw $ra, 4($sp) \n\t" \
4099 "addu $sp, $sp, 8 \n\t" \
4100 "move %0, $v0\n" \
4101 : /*out*/ "=r" (_res) \
4102 : /*in*/ "0" (&_argvec[0]) \
4103 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4104 ); \
4105 lval = (__typeof__(lval)) _res; \
4106 } while (0)
4107
4108#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4109 arg7) \
4110 do { \
4111 volatile OrigFn _orig = (orig); \
4112 volatile unsigned long _argvec[8]; \
4113 volatile unsigned long _res; \
4114 _argvec[0] = (unsigned long)_orig.nraddr; \
4115 _argvec[1] = (unsigned long)(arg1); \
4116 _argvec[2] = (unsigned long)(arg2); \
4117 _argvec[3] = (unsigned long)(arg3); \
4118 _argvec[4] = (unsigned long)(arg4); \
4119 _argvec[5] = (unsigned long)(arg5); \
4120 _argvec[6] = (unsigned long)(arg6); \
4121 _argvec[7] = (unsigned long)(arg7); \
4122 __asm__ volatile( \
4123 "subu $29, $29, 8 \n\t" \
4124 "sw $gp, 0($sp) \n\t" \
4125 "sw $ra, 4($sp) \n\t" \
4126 "lw $a0, 20(%1) \n\t" \
4127 "subu $sp, $sp, 32\n\t" \
4128 "sw $a0, 16($sp) \n\t" \
4129 "lw $a0, 24(%1) \n\t" \
4130 "sw $a0, 20($sp) \n\t" \
4131 "lw $a0, 28(%1) \n\t" \
4132 "sw $a0, 24($sp) \n\t" \
4133 "lw $a0, 4(%1) \n\t" \
4134 "lw $a1, 8(%1) \n\t" \
4135 "lw $a2, 12(%1) \n\t" \
4136 "lw $a3, 16(%1) \n\t" \
4137 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
4138 VALGRIND_CALL_NOREDIR_T9 \
4139 "addu $sp, $sp, 32 \n\t" \
4140 "lw $gp, 0($sp) \n\t" \
4141 "lw $ra, 4($sp) \n\t" \
4142 "addu $sp, $sp, 8 \n\t" \
4143 "move %0, $v0\n" \
4144 : /*out*/ "=r" (_res) \
4145 : /*in*/ "0" (&_argvec[0]) \
4146 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4147 ); \
4148 lval = (__typeof__(lval)) _res; \
4149 } while (0)
4150
4151#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4152 arg7,arg8) \
4153 do { \
4154 volatile OrigFn _orig = (orig); \
4155 volatile unsigned long _argvec[9]; \
4156 volatile unsigned long _res; \
4157 _argvec[0] = (unsigned long)_orig.nraddr; \
4158 _argvec[1] = (unsigned long)(arg1); \
4159 _argvec[2] = (unsigned long)(arg2); \
4160 _argvec[3] = (unsigned long)(arg3); \
4161 _argvec[4] = (unsigned long)(arg4); \
4162 _argvec[5] = (unsigned long)(arg5); \
4163 _argvec[6] = (unsigned long)(arg6); \
4164 _argvec[7] = (unsigned long)(arg7); \
4165 _argvec[8] = (unsigned long)(arg8); \
4166 __asm__ volatile( \
4167 "subu $29, $29, 8 \n\t" \
4168 "sw $gp, 0($sp) \n\t" \
4169 "sw $ra, 4($sp) \n\t" \
4170 "lw $a0, 20(%1) \n\t" \
4171 "subu $sp, $sp, 40\n\t" \
4172 "sw $a0, 16($sp) \n\t" \
4173 "lw $a0, 24(%1) \n\t" \
4174 "sw $a0, 20($sp) \n\t" \
4175 "lw $a0, 28(%1) \n\t" \
4176 "sw $a0, 24($sp) \n\t" \
4177 "lw $a0, 32(%1) \n\t" \
4178 "sw $a0, 28($sp) \n\t" \
4179 "lw $a0, 4(%1) \n\t" \
4180 "lw $a1, 8(%1) \n\t" \
4181 "lw $a2, 12(%1) \n\t" \
4182 "lw $a3, 16(%1) \n\t" \
4183 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
4184 VALGRIND_CALL_NOREDIR_T9 \
4185 "addu $sp, $sp, 40 \n\t" \
4186 "lw $gp, 0($sp) \n\t" \
4187 "lw $ra, 4($sp) \n\t" \
4188 "addu $sp, $sp, 8 \n\t" \
4189 "move %0, $v0\n" \
4190 : /*out*/ "=r" (_res) \
4191 : /*in*/ "0" (&_argvec[0]) \
4192 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4193 ); \
4194 lval = (__typeof__(lval)) _res; \
4195 } while (0)
4196
4197#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4198 arg7,arg8,arg9) \
4199 do { \
4200 volatile OrigFn _orig = (orig); \
4201 volatile unsigned long _argvec[10]; \
4202 volatile unsigned long _res; \
4203 _argvec[0] = (unsigned long)_orig.nraddr; \
4204 _argvec[1] = (unsigned long)(arg1); \
4205 _argvec[2] = (unsigned long)(arg2); \
4206 _argvec[3] = (unsigned long)(arg3); \
4207 _argvec[4] = (unsigned long)(arg4); \
4208 _argvec[5] = (unsigned long)(arg5); \
4209 _argvec[6] = (unsigned long)(arg6); \
4210 _argvec[7] = (unsigned long)(arg7); \
4211 _argvec[8] = (unsigned long)(arg8); \
4212 _argvec[9] = (unsigned long)(arg9); \
4213 __asm__ volatile( \
4214 "subu $29, $29, 8 \n\t" \
4215 "sw $gp, 0($sp) \n\t" \
4216 "sw $ra, 4($sp) \n\t" \
4217 "lw $a0, 20(%1) \n\t" \
4218 "subu $sp, $sp, 40\n\t" \
4219 "sw $a0, 16($sp) \n\t" \
4220 "lw $a0, 24(%1) \n\t" \
4221 "sw $a0, 20($sp) \n\t" \
4222 "lw $a0, 28(%1) \n\t" \
4223 "sw $a0, 24($sp) \n\t" \
4224 "lw $a0, 32(%1) \n\t" \
4225 "sw $a0, 28($sp) \n\t" \
4226 "lw $a0, 36(%1) \n\t" \
4227 "sw $a0, 32($sp) \n\t" \
4228 "lw $a0, 4(%1) \n\t" \
4229 "lw $a1, 8(%1) \n\t" \
4230 "lw $a2, 12(%1) \n\t" \
4231 "lw $a3, 16(%1) \n\t" \
4232 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
4233 VALGRIND_CALL_NOREDIR_T9 \
4234 "addu $sp, $sp, 40 \n\t" \
4235 "lw $gp, 0($sp) \n\t" \
4236 "lw $ra, 4($sp) \n\t" \
4237 "addu $sp, $sp, 8 \n\t" \
4238 "move %0, $v0\n" \
4239 : /*out*/ "=r" (_res) \
4240 : /*in*/ "0" (&_argvec[0]) \
4241 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4242 ); \
4243 lval = (__typeof__(lval)) _res; \
4244 } while (0)
4245
4246#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4247 arg7,arg8,arg9,arg10) \
4248 do { \
4249 volatile OrigFn _orig = (orig); \
4250 volatile unsigned long _argvec[11]; \
4251 volatile unsigned long _res; \
4252 _argvec[0] = (unsigned long)_orig.nraddr; \
4253 _argvec[1] = (unsigned long)(arg1); \
4254 _argvec[2] = (unsigned long)(arg2); \
4255 _argvec[3] = (unsigned long)(arg3); \
4256 _argvec[4] = (unsigned long)(arg4); \
4257 _argvec[5] = (unsigned long)(arg5); \
4258 _argvec[6] = (unsigned long)(arg6); \
4259 _argvec[7] = (unsigned long)(arg7); \
4260 _argvec[8] = (unsigned long)(arg8); \
4261 _argvec[9] = (unsigned long)(arg9); \
4262 _argvec[10] = (unsigned long)(arg10); \
4263 __asm__ volatile( \
4264 "subu $29, $29, 8 \n\t" \
4265 "sw $gp, 0($sp) \n\t" \
4266 "sw $ra, 4($sp) \n\t" \
4267 "lw $a0, 20(%1) \n\t" \
4268 "subu $sp, $sp, 48\n\t" \
4269 "sw $a0, 16($sp) \n\t" \
4270 "lw $a0, 24(%1) \n\t" \
4271 "sw $a0, 20($sp) \n\t" \
4272 "lw $a0, 28(%1) \n\t" \
4273 "sw $a0, 24($sp) \n\t" \
4274 "lw $a0, 32(%1) \n\t" \
4275 "sw $a0, 28($sp) \n\t" \
4276 "lw $a0, 36(%1) \n\t" \
4277 "sw $a0, 32($sp) \n\t" \
4278 "lw $a0, 40(%1) \n\t" \
4279 "sw $a0, 36($sp) \n\t" \
4280 "lw $a0, 4(%1) \n\t" \
4281 "lw $a1, 8(%1) \n\t" \
4282 "lw $a2, 12(%1) \n\t" \
4283 "lw $a3, 16(%1) \n\t" \
4284 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
4285 VALGRIND_CALL_NOREDIR_T9 \
4286 "addu $sp, $sp, 48 \n\t" \
4287 "lw $gp, 0($sp) \n\t" \
4288 "lw $ra, 4($sp) \n\t" \
4289 "addu $sp, $sp, 8 \n\t" \
4290 "move %0, $v0\n" \
4291 : /*out*/ "=r" (_res) \
4292 : /*in*/ "0" (&_argvec[0]) \
4293 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4294 ); \
4295 lval = (__typeof__(lval)) _res; \
4296 } while (0)
4297
4298#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
4299 arg6,arg7,arg8,arg9,arg10, \
4300 arg11) \
4301 do { \
4302 volatile OrigFn _orig = (orig); \
4303 volatile unsigned long _argvec[12]; \
4304 volatile unsigned long _res; \
4305 _argvec[0] = (unsigned long)_orig.nraddr; \
4306 _argvec[1] = (unsigned long)(arg1); \
4307 _argvec[2] = (unsigned long)(arg2); \
4308 _argvec[3] = (unsigned long)(arg3); \
4309 _argvec[4] = (unsigned long)(arg4); \
4310 _argvec[5] = (unsigned long)(arg5); \
4311 _argvec[6] = (unsigned long)(arg6); \
4312 _argvec[7] = (unsigned long)(arg7); \
4313 _argvec[8] = (unsigned long)(arg8); \
4314 _argvec[9] = (unsigned long)(arg9); \
4315 _argvec[10] = (unsigned long)(arg10); \
4316 _argvec[11] = (unsigned long)(arg11); \
4317 __asm__ volatile( \
4318 "subu $29, $29, 8 \n\t" \
4319 "sw $gp, 0($sp) \n\t" \
4320 "sw $ra, 4($sp) \n\t" \
4321 "lw $a0, 20(%1) \n\t" \
4322 "subu $sp, $sp, 48\n\t" \
4323 "sw $a0, 16($sp) \n\t" \
4324 "lw $a0, 24(%1) \n\t" \
4325 "sw $a0, 20($sp) \n\t" \
4326 "lw $a0, 28(%1) \n\t" \
4327 "sw $a0, 24($sp) \n\t" \
4328 "lw $a0, 32(%1) \n\t" \
4329 "sw $a0, 28($sp) \n\t" \
4330 "lw $a0, 36(%1) \n\t" \
4331 "sw $a0, 32($sp) \n\t" \
4332 "lw $a0, 40(%1) \n\t" \
4333 "sw $a0, 36($sp) \n\t" \
4334 "lw $a0, 44(%1) \n\t" \
4335 "sw $a0, 40($sp) \n\t" \
4336 "lw $a0, 4(%1) \n\t" \
4337 "lw $a1, 8(%1) \n\t" \
4338 "lw $a2, 12(%1) \n\t" \
4339 "lw $a3, 16(%1) \n\t" \
4340 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
4341 VALGRIND_CALL_NOREDIR_T9 \
4342 "addu $sp, $sp, 48 \n\t" \
4343 "lw $gp, 0($sp) \n\t" \
4344 "lw $ra, 4($sp) \n\t" \
4345 "addu $sp, $sp, 8 \n\t" \
4346 "move %0, $v0\n" \
4347 : /*out*/ "=r" (_res) \
4348 : /*in*/ "0" (&_argvec[0]) \
4349 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4350 ); \
4351 lval = (__typeof__(lval)) _res; \
4352 } while (0)
4353
4354#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
4355 arg6,arg7,arg8,arg9,arg10, \
4356 arg11,arg12) \
4357 do { \
4358 volatile OrigFn _orig = (orig); \
4359 volatile unsigned long _argvec[13]; \
4360 volatile unsigned long _res; \
4361 _argvec[0] = (unsigned long)_orig.nraddr; \
4362 _argvec[1] = (unsigned long)(arg1); \
4363 _argvec[2] = (unsigned long)(arg2); \
4364 _argvec[3] = (unsigned long)(arg3); \
4365 _argvec[4] = (unsigned long)(arg4); \
4366 _argvec[5] = (unsigned long)(arg5); \
4367 _argvec[6] = (unsigned long)(arg6); \
4368 _argvec[7] = (unsigned long)(arg7); \
4369 _argvec[8] = (unsigned long)(arg8); \
4370 _argvec[9] = (unsigned long)(arg9); \
4371 _argvec[10] = (unsigned long)(arg10); \
4372 _argvec[11] = (unsigned long)(arg11); \
4373 _argvec[12] = (unsigned long)(arg12); \
4374 __asm__ volatile( \
4375 "subu $29, $29, 8 \n\t" \
4376 "sw $gp, 0($sp) \n\t" \
4377 "sw $ra, 4($sp) \n\t" \
4378 "lw $a0, 20(%1) \n\t" \
4379 "subu $sp, $sp, 56\n\t" \
4380 "sw $a0, 16($sp) \n\t" \
4381 "lw $a0, 24(%1) \n\t" \
4382 "sw $a0, 20($sp) \n\t" \
4383 "lw $a0, 28(%1) \n\t" \
4384 "sw $a0, 24($sp) \n\t" \
4385 "lw $a0, 32(%1) \n\t" \
4386 "sw $a0, 28($sp) \n\t" \
4387 "lw $a0, 36(%1) \n\t" \
4388 "sw $a0, 32($sp) \n\t" \
4389 "lw $a0, 40(%1) \n\t" \
4390 "sw $a0, 36($sp) \n\t" \
4391 "lw $a0, 44(%1) \n\t" \
4392 "sw $a0, 40($sp) \n\t" \
4393 "lw $a0, 48(%1) \n\t" \
4394 "sw $a0, 44($sp) \n\t" \
4395 "lw $a0, 4(%1) \n\t" \
4396 "lw $a1, 8(%1) \n\t" \
4397 "lw $a2, 12(%1) \n\t" \
4398 "lw $a3, 16(%1) \n\t" \
4399 "lw $t9, 0(%1) \n\t" /* target->t9 */ \
4400 VALGRIND_CALL_NOREDIR_T9 \
4401 "addu $sp, $sp, 56 \n\t" \
4402 "lw $gp, 0($sp) \n\t" \
4403 "lw $ra, 4($sp) \n\t" \
4404 "addu $sp, $sp, 8 \n\t" \
4405 "move %0, $v0\n" \
4406 : /*out*/ "=r" (_res) \
4407 : /*in*/ "0" (&_argvec[0]) \
4408 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4409 ); \
4410 lval = (__typeof__(lval)) _res; \
4411 } while (0)
4412
4413#endif /* PLAT_mips32_linux */
4414
sewardj0ec07f32006-01-12 12:32:32 +00004415
4416/* ------------------------------------------------------------------ */
4417/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
4418/* */
njn30d76c62005-06-18 15:07:39 +00004419/* ------------------------------------------------------------------ */
4420
sewardj2e93c502002-04-12 11:12:52 +00004421/* Some request codes. There are many more of these, but most are not
4422 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00004423 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00004424
sewardj0ec07f32006-01-12 12:32:32 +00004425 Core ones are in the range 0x00000000--0x0000ffff. The non-public
4426 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00004427*/
4428
sewardj0ec07f32006-01-12 12:32:32 +00004429/* These macros are used by tools -- they must be public, but don't
4430 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00004431#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00004432 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00004433#define VG_IS_TOOL_USERREQ(a, b, v) \
4434 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00004435
sewardj5ce4b152006-03-11 12:57:41 +00004436/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
4437 This enum comprises an ABI exported by Valgrind to programs
4438 which use client requests. DO NOT CHANGE THE ORDER OF THESE
4439 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00004440typedef
njn4c791212003-05-02 17:53:54 +00004441 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
4442 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00004443
sewardj0ec07f32006-01-12 12:32:32 +00004444 /* These allow any function to be called from the simulated
4445 CPU but run on the real CPU. Nb: the first arg passed to
4446 the function is always the ThreadId of the running
4447 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00004448 function, etc. */
njn4c791212003-05-02 17:53:54 +00004449 VG_USERREQ__CLIENT_CALL0 = 0x1101,
4450 VG_USERREQ__CLIENT_CALL1 = 0x1102,
4451 VG_USERREQ__CLIENT_CALL2 = 0x1103,
4452 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00004453
sewardj0ec07f32006-01-12 12:32:32 +00004454 /* Can be useful in regression testing suites -- eg. can
4455 send Valgrind's output to /dev/null and still count
4456 errors. */
njn4c791212003-05-02 17:53:54 +00004457 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00004458
sewardj3b290482011-05-06 21:02:55 +00004459 /* Allows a string (gdb monitor command) to be passed to the tool
4460 Used for interaction with vgdb/gdb */
4461 VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
4462
sewardj0ec07f32006-01-12 12:32:32 +00004463 /* These are useful and can be interpreted by any tool that
4464 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00004465 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
bart91347382011-03-25 20:07:25 +00004466 VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
njnd7994182003-10-02 13:44:04 +00004467 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00004468 /* Memory pool support. */
4469 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
4470 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
4471 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
4472 VG_USERREQ__MEMPOOL_FREE = 0x1306,
sewardj2c1c9df2006-07-28 00:06:37 +00004473 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
sewardjc740d762006-10-05 17:59:23 +00004474 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
4475 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
4476 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
njnd7994182003-10-02 13:44:04 +00004477
fitzhardinge39de4b42003-10-31 07:12:21 +00004478 /* Allow printfs to valgrind log. */
sewardjc560fb32010-01-28 15:23:54 +00004479 /* The first two pass the va_list argument by value, which
4480 assumes it is the same size as or smaller than a UWord,
4481 which generally isn't the case. Hence are deprecated.
4482 The second two pass the vargs by reference and so are
4483 immune to this problem. */
4484 /* both :: char* fmt, va_list vargs (DEPRECATED) */
njn30d76c62005-06-18 15:07:39 +00004485 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00004486 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
sewardjc560fb32010-01-28 15:23:54 +00004487 /* both :: char* fmt, va_list* vargs */
4488 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
4489 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
rjwalsh0140af52005-06-04 20:42:33 +00004490
4491 /* Stack support. */
4492 VG_USERREQ__STACK_REGISTER = 0x1501,
4493 VG_USERREQ__STACK_DEREGISTER = 0x1502,
sewardjc8259b82009-04-22 22:42:10 +00004494 VG_USERREQ__STACK_CHANGE = 0x1503,
4495
4496 /* Wine support */
sewardj5c659622010-08-20 18:22:07 +00004497 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
4498
4499 /* Querying of debug info. */
sewardjdc873c02011-07-24 16:02:33 +00004500 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
4501
4502 /* Disable/enable error reporting level. Takes a single
4503 Word arg which is the delta to this thread's error
4504 disablement indicator. Hence 1 disables or further
4505 disables errors, and -1 moves back towards enablement.
4506 Other values are not allowed. */
florianbb913cd2012-08-28 16:50:39 +00004507 VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801,
4508
4509 /* Initialise IR injection */
4510 VG_USERREQ__VEX_INIT_FOR_IRI = 0x1901
njn25e49d8e72002-09-23 09:36:25 +00004511 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00004512
sewardj0ec07f32006-01-12 12:32:32 +00004513#if !defined(__GNUC__)
4514# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00004515#endif
sewardj2e93c502002-04-12 11:12:52 +00004516
bartfa5115a2010-09-02 09:33:02 +00004517
sewardj0ec07f32006-01-12 12:32:32 +00004518/* Returns the number of Valgrinds this code is running under. That
4519 is, 0 if running natively, 1 if running under Valgrind, 2 if
4520 running under Valgrind which is running under another Valgrind,
4521 etc. */
bartfa5115a2010-09-02 09:33:02 +00004522#define RUNNING_ON_VALGRIND \
bart575ce8e2011-05-15 07:04:03 +00004523 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \
bartfa5115a2010-09-02 09:33:02 +00004524 VG_USERREQ__RUNNING_ON_VALGRIND, \
4525 0, 0, 0, 0, 0) \
sewardjde4a1d02002-03-22 01:27:54 +00004526
4527
sewardj18d75132002-05-16 11:06:21 +00004528/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
4529 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
4530 since it provides a way to make sure valgrind will retranslate the
4531 invalidated area. Returns no value. */
sewardj4b3a7422011-10-24 13:21:57 +00004532#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
4533 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DISCARD_TRANSLATIONS, \
4534 _qzz_addr, _qzz_len, 0, 0, 0)
sewardj18d75132002-05-16 11:06:21 +00004535
njn26aba4d2005-05-16 13:31:23 +00004536
sewardj0ec07f32006-01-12 12:32:32 +00004537/* These requests are for getting Valgrind itself to print something.
njnd55f0d92009-08-03 01:38:56 +00004538 Possibly with a backtrace. This is a really ugly hack. The return value
4539 is the number of characters printed, excluding the "**<pid>** " part at the
4540 start and the backtrace (if present). */
sewardj0ec07f32006-01-12 12:32:32 +00004541
bart42f83fe2012-01-31 10:13:51 +00004542#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00004543/* Modern GCC will optimize the static routine out if unused,
4544 and unused attribute will shut down warnings about it. */
4545static int VALGRIND_PRINTF(const char *format, ...)
4546 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00004547#endif
sewardj7eca0cc2006-04-12 17:15:35 +00004548static int
bart0da2c772010-09-01 10:18:36 +00004549#if defined(_MSC_VER)
4550__inline
4551#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00004552VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00004553{
bart8c7e25f2011-03-04 16:55:56 +00004554#if defined(NVALGRIND)
4555 return 0;
4556#else /* NVALGRIND */
bart575ce8e2011-05-15 07:04:03 +00004557#if defined(_MSC_VER)
4558 uintptr_t _qzz_res;
4559#else
njnc6168192004-11-29 13:54:10 +00004560 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00004561#endif
sewardjc560fb32010-01-28 15:23:54 +00004562 va_list vargs;
4563 va_start(vargs, format);
bart0da2c772010-09-01 10:18:36 +00004564#if defined(_MSC_VER)
bart575ce8e2011-05-15 07:04:03 +00004565 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00004566 VG_USERREQ__PRINTF_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00004567 (uintptr_t)format,
4568 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00004569 0, 0, 0);
4570#else
bart575ce8e2011-05-15 07:04:03 +00004571 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00004572 VG_USERREQ__PRINTF_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00004573 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00004574 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00004575 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00004576#endif
sewardjc560fb32010-01-28 15:23:54 +00004577 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00004578 return (int)_qzz_res;
bart8c7e25f2011-03-04 16:55:56 +00004579#endif /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00004580}
4581
bart42f83fe2012-01-31 10:13:51 +00004582#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00004583static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
4584 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00004585#endif
sewardj7eca0cc2006-04-12 17:15:35 +00004586static int
bart0da2c772010-09-01 10:18:36 +00004587#if defined(_MSC_VER)
4588__inline
4589#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00004590VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00004591{
bart8c7e25f2011-03-04 16:55:56 +00004592#if defined(NVALGRIND)
4593 return 0;
4594#else /* NVALGRIND */
bart575ce8e2011-05-15 07:04:03 +00004595#if defined(_MSC_VER)
4596 uintptr_t _qzz_res;
4597#else
njnc6168192004-11-29 13:54:10 +00004598 unsigned long _qzz_res;
bart575ce8e2011-05-15 07:04:03 +00004599#endif
sewardjc560fb32010-01-28 15:23:54 +00004600 va_list vargs;
4601 va_start(vargs, format);
bart0da2c772010-09-01 10:18:36 +00004602#if defined(_MSC_VER)
bart575ce8e2011-05-15 07:04:03 +00004603 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
bart0da2c772010-09-01 10:18:36 +00004604 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00004605 (uintptr_t)format,
4606 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00004607 0, 0, 0);
4608#else
bart575ce8e2011-05-15 07:04:03 +00004609 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
sewardjc560fb32010-01-28 15:23:54 +00004610 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00004611 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00004612 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00004613 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00004614#endif
sewardjc560fb32010-01-28 15:23:54 +00004615 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00004616 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00004617#endif /* NVALGRIND */
bart8c7e25f2011-03-04 16:55:56 +00004618}
sewardj18d75132002-05-16 11:06:21 +00004619
sewardj0ec07f32006-01-12 12:32:32 +00004620
njn3e884182003-04-15 13:03:23 +00004621/* These requests allow control to move from the simulated CPU to the
njn1319b492006-11-20 22:02:40 +00004622 real CPU, calling an arbitary function.
4623
4624 Note that the current ThreadId is inserted as the first argument.
4625 So this call:
4626
4627 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
4628
4629 requires f to have this signature:
4630
4631 Word f(Word tid, Word arg1, Word arg2)
4632
4633 where "Word" is a word-sized type.
njn45fb4d32007-12-05 21:51:50 +00004634
4635 Note that these client requests are not entirely reliable. For example,
4636 if you call a function with them that subsequently calls printf(),
4637 there's a high chance Valgrind will crash. Generally, your prospects of
4638 these working are made higher if the called function does not refer to
4639 any global variables, and does not refer to any libc or other functions
4640 (printf et al). Any kind of entanglement with libc or dynamic linking is
4641 likely to have a bad outcome, for tricky reasons which we've grappled
4642 with a lot in the past.
njn1319b492006-11-20 22:02:40 +00004643*/
sewardj0ec07f32006-01-12 12:32:32 +00004644#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
bart575ce8e2011-05-15 07:04:03 +00004645 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
4646 VG_USERREQ__CLIENT_CALL0, \
4647 _qyy_fn, \
4648 0, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00004649
bart575ce8e2011-05-15 07:04:03 +00004650#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
4651 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
4652 VG_USERREQ__CLIENT_CALL1, \
4653 _qyy_fn, \
4654 _qyy_arg1, 0, 0, 0)
njn3e884182003-04-15 13:03:23 +00004655
bart575ce8e2011-05-15 07:04:03 +00004656#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
4657 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
4658 VG_USERREQ__CLIENT_CALL2, \
4659 _qyy_fn, \
4660 _qyy_arg1, _qyy_arg2, 0, 0)
njn3e884182003-04-15 13:03:23 +00004661
sewardj0ec07f32006-01-12 12:32:32 +00004662#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
bart575ce8e2011-05-15 07:04:03 +00004663 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
4664 VG_USERREQ__CLIENT_CALL3, \
4665 _qyy_fn, \
4666 _qyy_arg1, _qyy_arg2, \
4667 _qyy_arg3, 0)
njn3e884182003-04-15 13:03:23 +00004668
4669
nethercote7cc9c232004-01-21 15:08:04 +00004670/* Counts the number of errors that have been recorded by a tool. Nb:
4671 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00004672 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00004673#define VALGRIND_COUNT_ERRORS \
bart575ce8e2011-05-15 07:04:03 +00004674 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR( \
4675 0 /* default return */, \
sewardj0ec07f32006-01-12 12:32:32 +00004676 VG_USERREQ__COUNT_ERRORS, \
bart575ce8e2011-05-15 07:04:03 +00004677 0, 0, 0, 0, 0)
njn47363ab2003-04-21 13:24:40 +00004678
njn3ac96952009-07-09 23:35:44 +00004679/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
4680 when heap blocks are allocated in order to give accurate results. This
4681 happens automatically for the standard allocator functions such as
4682 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
4683 delete[], etc.
njnd7994182003-10-02 13:44:04 +00004684
njn3ac96952009-07-09 23:35:44 +00004685 But if your program uses a custom allocator, this doesn't automatically
4686 happen, and Valgrind will not do as well. For example, if you allocate
4687 superblocks with mmap() and then allocates chunks of the superblocks, all
4688 Valgrind's observations will be at the mmap() level and it won't know that
4689 the chunks should be considered separate entities. In Memcheck's case,
4690 that means you probably won't get heap block overrun detection (because
4691 there won't be redzones marked as unaddressable) and you definitely won't
4692 get any leak detection.
4693
4694 The following client requests allow a custom allocator to be annotated so
4695 that it can be handled accurately by Valgrind.
4696
4697 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
4698 by a malloc()-like function. For Memcheck (an illustrative case), this
4699 does two things:
4700
4701 - It records that the block has been allocated. This means any addresses
4702 within the block mentioned in error messages will be
4703 identified as belonging to the block. It also means that if the block
4704 isn't freed it will be detected by the leak checker.
4705
4706 - It marks the block as being addressable and undefined (if 'is_zeroed' is
4707 not set), or addressable and defined (if 'is_zeroed' is set). This
4708 controls how accesses to the block by the program are handled.
4709
4710 'addr' is the start of the usable block (ie. after any
4711 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
4712 can apply redzones -- these are blocks of padding at the start and end of
4713 each block. Adding redzones is recommended as it makes it much more likely
4714 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
4715 zeroed (or filled with another predictable value), as is the case for
4716 calloc().
4717
4718 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
4719 heap block -- that will be used by the client program -- is allocated.
4720 It's best to put it at the outermost level of the allocator if possible;
4721 for example, if you have a function my_alloc() which calls
4722 internal_alloc(), and the client request is put inside internal_alloc(),
4723 stack traces relating to the heap block will contain entries for both
4724 my_alloc() and internal_alloc(), which is probably not what you want.
4725
njnb965efb2009-08-10 07:36:54 +00004726 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
4727 custom blocks from within a heap block, B, that has been allocated with
4728 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
4729 -- the custom blocks will take precedence.
4730
njn3ac96952009-07-09 23:35:44 +00004731 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
4732 Memcheck, it does two things:
4733
4734 - It records that the block has been deallocated. This assumes that the
4735 block was annotated as having been allocated via
4736 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
4737
4738 - It marks the block as being unaddressable.
4739
4740 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
4741 heap block is deallocated.
4742
bart91347382011-03-25 20:07:25 +00004743 VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For
4744 Memcheck, it does four things:
4745
4746 - It records that the size of a block has been changed. This assumes that
4747 the block was annotated as having been allocated via
4748 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
4749
4750 - If the block shrunk, it marks the freed memory as being unaddressable.
4751
4752 - If the block grew, it marks the new area as undefined and defines a red
4753 zone past the end of the new block.
4754
4755 - The V-bits of the overlap between the old and the new block are preserved.
4756
4757 VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block
4758 and before deallocation of the old block.
4759
4760 In many cases, these three client requests will not be enough to get your
njn3ac96952009-07-09 23:35:44 +00004761 allocator working well with Memcheck. More specifically, if your allocator
4762 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
4763 will be necessary to mark the memory as addressable just before the zeroing
4764 occurs, otherwise you'll get a lot of invalid write errors. For example,
4765 you'll need to do this if your allocator recycles freed blocks, but it
4766 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
4767 Alternatively, if your allocator reuses freed blocks for allocator-internal
4768 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
4769
4770 Really, what's happening is a blurring of the lines between the client
4771 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
4772 memory should be considered unaddressable to the client program, but the
4773 allocator knows more than the rest of the client program and so may be able
4774 to safely access it. Extra client requests are necessary for Valgrind to
4775 understand the distinction between the allocator and the rest of the
4776 program.
4777
njn32f8d8c2009-07-15 02:31:45 +00004778 Ignored if addr == 0.
njn3ac96952009-07-09 23:35:44 +00004779*/
sewardj4b3a7422011-10-24 13:21:57 +00004780#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
4781 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MALLOCLIKE_BLOCK, \
4782 addr, sizeB, rzB, is_zeroed, 0)
njnd7994182003-10-02 13:44:04 +00004783
njn32f8d8c2009-07-15 02:31:45 +00004784/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
4785 Ignored if addr == 0.
4786*/
sewardj4b3a7422011-10-24 13:21:57 +00004787#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \
4788 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RESIZEINPLACE_BLOCK, \
4789 addr, oldSizeB, newSizeB, rzB, 0)
bart91347382011-03-25 20:07:25 +00004790
4791/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
4792 Ignored if addr == 0.
4793*/
sewardj4b3a7422011-10-24 13:21:57 +00004794#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
4795 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREELIKE_BLOCK, \
4796 addr, rzB, 0, 0, 0)
njnd7994182003-10-02 13:44:04 +00004797
rjwalshbc0bb832004-06-19 18:12:36 +00004798/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004799#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
sewardj4b3a7422011-10-24 13:21:57 +00004800 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \
4801 pool, rzB, is_zeroed, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00004802
4803/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004804#define VALGRIND_DESTROY_MEMPOOL(pool) \
sewardj4b3a7422011-10-24 13:21:57 +00004805 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DESTROY_MEMPOOL, \
4806 pool, 0, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00004807
4808/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004809#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
sewardj4b3a7422011-10-24 13:21:57 +00004810 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_ALLOC, \
4811 pool, addr, size, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00004812
4813/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004814#define VALGRIND_MEMPOOL_FREE(pool, addr) \
sewardj4b3a7422011-10-24 13:21:57 +00004815 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_FREE, \
4816 pool, addr, 0, 0, 0)
rjwalshbc0bb832004-06-19 18:12:36 +00004817
sewardj2c1c9df2006-07-28 00:06:37 +00004818/* Disassociate any pieces outside a particular range. */
4819#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
sewardj4b3a7422011-10-24 13:21:57 +00004820 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_TRIM, \
4821 pool, addr, size, 0, 0)
sewardj2c1c9df2006-07-28 00:06:37 +00004822
sewardjc740d762006-10-05 17:59:23 +00004823/* Resize and/or move a piece associated with a memory pool. */
4824#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
sewardj4b3a7422011-10-24 13:21:57 +00004825 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MOVE_MEMPOOL, \
4826 poolA, poolB, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00004827
4828/* Resize and/or move a piece associated with a memory pool. */
4829#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
sewardj4b3a7422011-10-24 13:21:57 +00004830 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_CHANGE, \
4831 pool, addrA, addrB, size, 0)
sewardjc740d762006-10-05 17:59:23 +00004832
4833/* Return 1 if a mempool exists, else 0. */
4834#define VALGRIND_MEMPOOL_EXISTS(pool) \
bart575ce8e2011-05-15 07:04:03 +00004835 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardjc740d762006-10-05 17:59:23 +00004836 VG_USERREQ__MEMPOOL_EXISTS, \
bart575ce8e2011-05-15 07:04:03 +00004837 pool, 0, 0, 0, 0)
sewardjc740d762006-10-05 17:59:23 +00004838
rjwalsh0140af52005-06-04 20:42:33 +00004839/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004840#define VALGRIND_STACK_REGISTER(start, end) \
bart575ce8e2011-05-15 07:04:03 +00004841 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj0ec07f32006-01-12 12:32:32 +00004842 VG_USERREQ__STACK_REGISTER, \
bart575ce8e2011-05-15 07:04:03 +00004843 start, end, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00004844
4845/* Unmark the piece of memory associated with a stack id as being a
4846 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00004847#define VALGRIND_STACK_DEREGISTER(id) \
sewardj4b3a7422011-10-24 13:21:57 +00004848 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_DEREGISTER, \
4849 id, 0, 0, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00004850
4851/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004852#define VALGRIND_STACK_CHANGE(id, start, end) \
sewardj4b3a7422011-10-24 13:21:57 +00004853 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_CHANGE, \
4854 id, start, end, 0, 0)
rjwalsh0140af52005-06-04 20:42:33 +00004855
sewardjc8259b82009-04-22 22:42:10 +00004856/* Load PDB debug info for Wine PE image_map. */
sewardj4b3a7422011-10-24 13:21:57 +00004857#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
4858 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LOAD_PDB_DEBUGINFO, \
4859 fd, ptr, total_size, delta, 0)
sewardjc8259b82009-04-22 22:42:10 +00004860
sewardj5c659622010-08-20 18:22:07 +00004861/* Map a code address to a source file name and line number. buf64
4862 must point to a 64-byte buffer in the caller's address space. The
4863 result will be dumped in there and is guaranteed to be zero
4864 terminated. If no info is found, the first byte is set to zero. */
4865#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \
bart575ce8e2011-05-15 07:04:03 +00004866 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
sewardj5c659622010-08-20 18:22:07 +00004867 VG_USERREQ__MAP_IP_TO_SRCLOC, \
bart575ce8e2011-05-15 07:04:03 +00004868 addr, buf64, 0, 0, 0)
sewardj5c659622010-08-20 18:22:07 +00004869
sewardjdc873c02011-07-24 16:02:33 +00004870/* Disable error reporting for this thread. Behaves in a stack like
4871 way, so you can safely call this multiple times provided that
4872 VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times
4873 to re-enable reporting. The first call of this macro disables
4874 reporting. Subsequent calls have no effect except to increase the
4875 number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable
4876 reporting. Child threads do not inherit this setting from their
4877 parents -- they are always created with reporting enabled. */
bart06e9bf02011-10-07 09:39:56 +00004878#define VALGRIND_DISABLE_ERROR_REPORTING \
sewardj4b3a7422011-10-24 13:21:57 +00004879 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
4880 1, 0, 0, 0, 0)
sewardjdc873c02011-07-24 16:02:33 +00004881
4882/* Re-enable error reporting, as per comments on
4883 VALGRIND_DISABLE_ERROR_REPORTING. */
bart06e9bf02011-10-07 09:39:56 +00004884#define VALGRIND_ENABLE_ERROR_REPORTING \
sewardj4b3a7422011-10-24 13:21:57 +00004885 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
4886 -1, 0, 0, 0, 0)
sewardj0ec07f32006-01-12 12:32:32 +00004887
sewardjc112c8e2011-06-24 18:26:11 +00004888#undef PLAT_x86_darwin
4889#undef PLAT_amd64_darwin
4890#undef PLAT_x86_win32
sewardjf5c1a7f2006-10-17 01:32:48 +00004891#undef PLAT_x86_linux
4892#undef PLAT_amd64_linux
4893#undef PLAT_ppc32_linux
4894#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +00004895#undef PLAT_arm_linux
sewardjb5b87402011-03-07 16:05:35 +00004896#undef PLAT_s390x_linux
sewardj5db15402012-06-07 09:13:21 +00004897#undef PLAT_mips32_linux
sewardj0ec07f32006-01-12 12:32:32 +00004898
njn3e884182003-04-15 13:03:23 +00004899#endif /* __VALGRIND_H */