blob: 8f5c508ae1793f5354e562181884308862686814 [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
sewardj9eecbbb2010-05-03 21:37:12 +000015 Copyright (C) 2000-2010 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
sewardj71044162010-03-03 22:57:47 +000092#define __VALGRIND_MINOR__ 6
93
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_ppc64_aix5
112#undef PLAT_ppc32_aix5
113#undef PLAT_x86_darwin
114#undef PLAT_amd64_darwin
bart7f489812010-08-27 10:05:27 +0000115#undef PLAT_x86_win32
sewardjf5c1a7f2006-10-17 01:32:48 +0000116#undef PLAT_x86_linux
117#undef PLAT_amd64_linux
118#undef PLAT_ppc32_linux
119#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +0000120#undef PLAT_arm_linux
sewardj0ec07f32006-01-12 12:32:32 +0000121
njnf76d27a2009-05-28 01:53:07 +0000122#if defined(_AIX) && defined(__64BIT__)
sewardjf5c1a7f2006-10-17 01:32:48 +0000123# define PLAT_ppc64_aix5 1
124#elif defined(_AIX) && !defined(__64BIT__)
125# define PLAT_ppc32_aix5 1
njnf76d27a2009-05-28 01:53:07 +0000126#elif defined(__APPLE__) && defined(__i386__)
127# define PLAT_x86_darwin 1
128#elif defined(__APPLE__) && defined(__x86_64__)
129# define PLAT_amd64_darwin 1
bart7f489812010-08-27 10:05:27 +0000130#elif defined(__MINGW32__) || defined(__CYGWIN32__) || defined(_WIN32) && defined(_M_IX86)
131# define PLAT_x86_win32 1
sewardj59570ff2010-01-01 11:59:33 +0000132#elif defined(__linux__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000133# define PLAT_x86_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000134#elif defined(__linux__) && defined(__x86_64__)
njnf76d27a2009-05-28 01:53:07 +0000135# define PLAT_amd64_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_ppc32_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000138#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000139# define PLAT_ppc64_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000140#elif defined(__linux__) && defined(__arm__)
141# define PLAT_arm_linux 1
njnf76d27a2009-05-28 01:53:07 +0000142#else
sewardjf5c1a7f2006-10-17 01:32:48 +0000143/* If we're not compiling for our target platform, don't generate
sewardj0ec07f32006-01-12 12:32:32 +0000144 any inline asms. */
sewardj0ec07f32006-01-12 12:32:32 +0000145# if !defined(NVALGRIND)
146# define NVALGRIND 1
147# endif
148#endif
149
150
njn30d76c62005-06-18 15:07:39 +0000151/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000152/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
153/* in here of use to end-users -- skip to the next section. */
njn30d76c62005-06-18 15:07:39 +0000154/* ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000155
sewardj0ec07f32006-01-12 12:32:32 +0000156#if defined(NVALGRIND)
njn26aba4d2005-05-16 13:31:23 +0000157
158/* Define NVALGRIND to completely remove the Valgrind magic sequence
sewardj0ec07f32006-01-12 12:32:32 +0000159 from the compiled code (analogous to NDEBUG's effects on
160 assert()) */
161#define VALGRIND_DO_CLIENT_REQUEST( \
162 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000163 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000164 { \
165 (_zzq_rlval) = (_zzq_default); \
njn26aba4d2005-05-16 13:31:23 +0000166 }
167
sewardj0ec07f32006-01-12 12:32:32 +0000168#else /* ! NVALGRIND */
nethercotee90c6832004-10-18 18:07:49 +0000169
sewardj0ec07f32006-01-12 12:32:32 +0000170/* The following defines the magic code sequences which the JITter
171 spots and handles magically. Don't look too closely at them as
172 they will rot your brain.
173
174 The assembly code sequences for all architectures is in this one
175 file. This is because this file must be stand-alone, and we don't
176 want to have multiple files.
177
178 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
179 value gets put in the return slot, so that everything works when
180 this is executed not under Valgrind. Args are passed in a memory
181 block, and so there's no intrinsic limit to the number that could
sewardj9af10a12006-02-01 14:59:42 +0000182 be passed, but it's currently five.
nethercotee90c6832004-10-18 18:07:49 +0000183
nethercote54265442004-10-26 12:56:58 +0000184 The macro args are:
185 _zzq_rlval result lvalue
186 _zzq_default default value (result returned when running on real CPU)
187 _zzq_request request code
sewardj9af10a12006-02-01 14:59:42 +0000188 _zzq_arg1..5 request params
nethercote54265442004-10-26 12:56:58 +0000189
sewardj0ec07f32006-01-12 12:32:32 +0000190 The other two macros are used to support function wrapping, and are
sewardjd68ac3e2006-01-20 14:31:57 +0000191 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
192 guest's NRADDR pseudo-register and whatever other information is
193 needed to safely run the call original from the wrapper: on
194 ppc64-linux, the R2 value at the divert point is also needed. This
195 information is abstracted into a user-visible type, OrigFn.
196
197 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
198 guest, but guarantees that the branch instruction will not be
199 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
200 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
201 complete inline asm, since it needs to be combined with more magic
202 inline asm stuff to be useful.
nethercotee90c6832004-10-18 18:07:49 +0000203*/
204
njnf76d27a2009-05-28 01:53:07 +0000205/* ------------------------- x86-{linux,darwin} ---------------- */
sewardjde4a4ab2005-03-23 13:10:32 +0000206
bart7f489812010-08-27 10:05:27 +0000207#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) || defined(PLAT_x86_win32) && defined(__GNUC__)
sewardjc8858442006-01-20 15:17:20 +0000208
209typedef
210 struct {
211 unsigned int nraddr; /* where's the code? */
212 }
213 OrigFn;
214
sewardj0ec07f32006-01-12 12:32:32 +0000215#define __SPECIAL_INSTRUCTION_PREAMBLE \
216 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000217 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000218
sewardj0ec07f32006-01-12 12:32:32 +0000219#define VALGRIND_DO_CLIENT_REQUEST( \
220 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000221 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
222 { volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000223 volatile unsigned int _zzq_result; \
224 _zzq_args[0] = (unsigned int)(_zzq_request); \
225 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
226 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
227 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
228 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000229 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000230 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
231 /* %EDX = client_request ( %EAX ) */ \
232 "xchgl %%ebx,%%ebx" \
233 : "=d" (_zzq_result) \
234 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
235 : "cc", "memory" \
236 ); \
237 _zzq_rlval = _zzq_result; \
cerion85665ca2005-06-20 15:51:07 +0000238 }
sewardj2c48c7b2005-11-29 13:05:56 +0000239
sewardjc8858442006-01-20 15:17:20 +0000240#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
241 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
242 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000243 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
244 /* %EAX = guest_NRADDR */ \
245 "xchgl %%ecx,%%ecx" \
246 : "=a" (__addr) \
247 : \
248 : "cc", "memory" \
249 ); \
sewardjc8858442006-01-20 15:17:20 +0000250 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000251 }
sewardj0ec07f32006-01-12 12:32:32 +0000252
253#define VALGRIND_CALL_NOREDIR_EAX \
254 __SPECIAL_INSTRUCTION_PREAMBLE \
255 /* call-noredir *%EAX */ \
256 "xchgl %%edx,%%edx\n\t"
bart7f489812010-08-27 10:05:27 +0000257#endif /* PLAT_x86_linux || PLAT_x86_darwin || PLAT_x86_win32 && __GNUC__ */
258
259/* ------------------------- x86-Win32 ------------------------- */
260
261#if defined(PLAT_x86_win32) && !defined(__GNUC__)
262
263typedef
264 struct {
265 unsigned int nraddr; /* where's the code? */
266 }
267 OrigFn;
268
269#if defined(_MSC_VER)
270
271#define __SPECIAL_INSTRUCTION_PREAMBLE \
272 __asm rol edi, 3 __asm rol edi, 13 \
273 __asm rol edi, 29 __asm rol edi, 19
274
275#define VALGRIND_DO_CLIENT_REQUEST( \
276 _zzq_rlval, _zzq_default, _zzq_request, \
277 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
bartfa5115a2010-09-02 09:33:02 +0000278 { volatile uintptr_t _zzq_args[6]; \
bart7f489812010-08-27 10:05:27 +0000279 volatile unsigned int _zzq_result; \
bartfa5115a2010-09-02 09:33:02 +0000280 _zzq_args[0] = (uintptr_t)(_zzq_request); \
281 _zzq_args[1] = (uintptr_t)(_zzq_arg1); \
282 _zzq_args[2] = (uintptr_t)(_zzq_arg2); \
283 _zzq_args[3] = (uintptr_t)(_zzq_arg3); \
284 _zzq_args[4] = (uintptr_t)(_zzq_arg4); \
285 _zzq_args[5] = (uintptr_t)(_zzq_arg5); \
bart7f489812010-08-27 10:05:27 +0000286 __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default \
287 __SPECIAL_INSTRUCTION_PREAMBLE \
288 /* %EDX = client_request ( %EAX ) */ \
289 __asm xchg ebx,ebx \
290 __asm mov _zzq_result, edx \
291 } \
292 _zzq_rlval = _zzq_result; \
293 }
294
295#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
296 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
297 volatile unsigned int __addr; \
298 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
299 /* %EAX = guest_NRADDR */ \
300 __asm xchg ecx,ecx \
301 __asm mov __addr, eax \
302 } \
303 _zzq_orig->nraddr = __addr; \
304 }
305
306#define VALGRIND_CALL_NOREDIR_EAX ERROR
307
308#else
309#error Unsupported compiler.
310#endif
311
312#endif /* PLAT_x86_win32 */
sewardj0ec07f32006-01-12 12:32:32 +0000313
njnf76d27a2009-05-28 01:53:07 +0000314/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000315
njnf76d27a2009-05-28 01:53:07 +0000316#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardjc8858442006-01-20 15:17:20 +0000317
318typedef
319 struct {
320 unsigned long long int nraddr; /* where's the code? */
321 }
322 OrigFn;
323
sewardj0ec07f32006-01-12 12:32:32 +0000324#define __SPECIAL_INSTRUCTION_PREAMBLE \
325 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000326 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000327
328#define VALGRIND_DO_CLIENT_REQUEST( \
329 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000330 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
331 { volatile unsigned long long int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000332 volatile unsigned long long int _zzq_result; \
333 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
334 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
335 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
336 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
337 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000338 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000339 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
340 /* %RDX = client_request ( %RAX ) */ \
341 "xchgq %%rbx,%%rbx" \
342 : "=d" (_zzq_result) \
343 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
344 : "cc", "memory" \
345 ); \
346 _zzq_rlval = _zzq_result; \
347 }
348
sewardjc8858442006-01-20 15:17:20 +0000349#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
350 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
351 volatile unsigned long long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000352 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
353 /* %RAX = guest_NRADDR */ \
354 "xchgq %%rcx,%%rcx" \
355 : "=a" (__addr) \
356 : \
357 : "cc", "memory" \
358 ); \
sewardjc8858442006-01-20 15:17:20 +0000359 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000360 }
361
362#define VALGRIND_CALL_NOREDIR_RAX \
363 __SPECIAL_INSTRUCTION_PREAMBLE \
364 /* call-noredir *%RAX */ \
365 "xchgq %%rdx,%%rdx\n\t"
njnf76d27a2009-05-28 01:53:07 +0000366#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +0000367
sewardjf5c1a7f2006-10-17 01:32:48 +0000368/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000369
sewardjf5c1a7f2006-10-17 01:32:48 +0000370#if defined(PLAT_ppc32_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000371
372typedef
373 struct {
sewardjc8858442006-01-20 15:17:20 +0000374 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000375 }
376 OrigFn;
377
sewardj0ec07f32006-01-12 12:32:32 +0000378#define __SPECIAL_INSTRUCTION_PREAMBLE \
379 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000380 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000381
382#define VALGRIND_DO_CLIENT_REQUEST( \
383 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000384 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000385 \
sewardj9af10a12006-02-01 14:59:42 +0000386 { unsigned int _zzq_args[6]; \
sewardj1c5bcb12006-12-08 21:29:46 +0000387 unsigned int _zzq_result; \
388 unsigned int* _zzq_ptr; \
sewardj0ec07f32006-01-12 12:32:32 +0000389 _zzq_args[0] = (unsigned int)(_zzq_request); \
390 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
391 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
392 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
393 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000394 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000395 _zzq_ptr = _zzq_args; \
sewardj1c5bcb12006-12-08 21:29:46 +0000396 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
397 "mr 4,%2\n\t" /*ptr*/ \
398 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj0ec07f32006-01-12 12:32:32 +0000399 /* %R3 = client_request ( %R4 ) */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000400 "or 1,1,1\n\t" \
401 "mr %0,3" /*result*/ \
402 : "=b" (_zzq_result) \
403 : "b" (_zzq_default), "b" (_zzq_ptr) \
404 : "cc", "memory", "r3", "r4"); \
sewardj0ec07f32006-01-12 12:32:32 +0000405 _zzq_rlval = _zzq_result; \
406 }
407
sewardjd68ac3e2006-01-20 14:31:57 +0000408#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
409 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj1c5bcb12006-12-08 21:29:46 +0000410 unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000411 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
412 /* %R3 = guest_NRADDR */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000413 "or 2,2,2\n\t" \
414 "mr %0,3" \
415 : "=b" (__addr) \
sewardj0ec07f32006-01-12 12:32:32 +0000416 : \
sewardj1c5bcb12006-12-08 21:29:46 +0000417 : "cc", "memory", "r3" \
sewardj0ec07f32006-01-12 12:32:32 +0000418 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000419 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000420 }
421
422#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
423 __SPECIAL_INSTRUCTION_PREAMBLE \
424 /* branch-and-link-to-noredir *%R11 */ \
425 "or 3,3,3\n\t"
sewardjf5c1a7f2006-10-17 01:32:48 +0000426#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000427
sewardjf5c1a7f2006-10-17 01:32:48 +0000428/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000429
sewardjf5c1a7f2006-10-17 01:32:48 +0000430#if defined(PLAT_ppc64_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000431
432typedef
433 struct {
434 unsigned long long int nraddr; /* where's the code? */
435 unsigned long long int r2; /* what tocptr do we need? */
436 }
437 OrigFn;
438
sewardj1a85f4f2006-01-12 21:15:35 +0000439#define __SPECIAL_INSTRUCTION_PREAMBLE \
440 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
441 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
442
sewardj0ec07f32006-01-12 12:32:32 +0000443#define VALGRIND_DO_CLIENT_REQUEST( \
444 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000445 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000446 \
sewardj9af10a12006-02-01 14:59:42 +0000447 { unsigned long long int _zzq_args[6]; \
sewardj1a85f4f2006-01-12 21:15:35 +0000448 register unsigned long long int _zzq_result __asm__("r3"); \
449 register unsigned long long int* _zzq_ptr __asm__("r4"); \
450 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
451 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
452 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
453 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
454 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000455 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000456 _zzq_ptr = _zzq_args; \
sewardj1a85f4f2006-01-12 21:15:35 +0000457 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
458 /* %R3 = client_request ( %R4 ) */ \
459 "or 1,1,1" \
460 : "=r" (_zzq_result) \
sewardj0ec07f32006-01-12 12:32:32 +0000461 : "0" (_zzq_default), "r" (_zzq_ptr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000462 : "cc", "memory"); \
463 _zzq_rlval = _zzq_result; \
sewardj0ec07f32006-01-12 12:32:32 +0000464 }
sewardj1a85f4f2006-01-12 21:15:35 +0000465
sewardjd68ac3e2006-01-20 14:31:57 +0000466#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
467 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
468 register unsigned long long int __addr __asm__("r3"); \
sewardj1a85f4f2006-01-12 21:15:35 +0000469 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
470 /* %R3 = guest_NRADDR */ \
471 "or 2,2,2" \
472 : "=r" (__addr) \
473 : \
474 : "cc", "memory" \
475 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000476 _zzq_orig->nraddr = __addr; \
477 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
478 /* %R3 = guest_NRADDR_GPR2 */ \
479 "or 4,4,4" \
480 : "=r" (__addr) \
481 : \
482 : "cc", "memory" \
483 ); \
484 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000485 }
486
487#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
488 __SPECIAL_INSTRUCTION_PREAMBLE \
489 /* branch-and-link-to-noredir *%R11 */ \
490 "or 3,3,3\n\t"
491
sewardjf5c1a7f2006-10-17 01:32:48 +0000492#endif /* PLAT_ppc64_linux */
cerion85665ca2005-06-20 15:51:07 +0000493
sewardj59570ff2010-01-01 11:59:33 +0000494/* ------------------------- arm-linux ------------------------- */
495
496#if defined(PLAT_arm_linux)
497
498typedef
499 struct {
500 unsigned int nraddr; /* where's the code? */
501 }
502 OrigFn;
503
504#define __SPECIAL_INSTRUCTION_PREAMBLE \
505 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
506 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
507
508#define VALGRIND_DO_CLIENT_REQUEST( \
509 _zzq_rlval, _zzq_default, _zzq_request, \
510 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
511 \
512 { volatile unsigned int _zzq_args[6]; \
513 volatile unsigned int _zzq_result; \
514 _zzq_args[0] = (unsigned int)(_zzq_request); \
515 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
516 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
517 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
518 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
519 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
520 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
521 "mov r4, %2\n\t" /*ptr*/ \
522 __SPECIAL_INSTRUCTION_PREAMBLE \
523 /* R3 = client_request ( R4 ) */ \
524 "orr r10, r10, r10\n\t" \
525 "mov %0, r3" /*result*/ \
526 : "=r" (_zzq_result) \
527 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
528 : "cc","memory", "r3", "r4"); \
529 _zzq_rlval = _zzq_result; \
530 }
531
532#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
533 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
534 unsigned int __addr; \
535 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
536 /* R3 = guest_NRADDR */ \
537 "orr r11, r11, r11\n\t" \
538 "mov %0, r3" \
539 : "=r" (__addr) \
540 : \
541 : "cc", "memory", "r3" \
542 ); \
543 _zzq_orig->nraddr = __addr; \
544 }
545
546#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
547 __SPECIAL_INSTRUCTION_PREAMBLE \
548 /* branch-and-link-to-noredir *%R4 */ \
549 "orr r12, r12, r12\n\t"
550
551#endif /* PLAT_arm_linux */
552
sewardjf5c1a7f2006-10-17 01:32:48 +0000553/* ------------------------ ppc32-aix5 ------------------------- */
554
555#if defined(PLAT_ppc32_aix5)
556
557typedef
558 struct {
559 unsigned int nraddr; /* where's the code? */
560 unsigned int r2; /* what tocptr do we need? */
561 }
562 OrigFn;
563
564#define __SPECIAL_INSTRUCTION_PREAMBLE \
565 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
566 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
567
568#define VALGRIND_DO_CLIENT_REQUEST( \
569 _zzq_rlval, _zzq_default, _zzq_request, \
570 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
571 \
572 { unsigned int _zzq_args[7]; \
573 register unsigned int _zzq_result; \
574 register unsigned int* _zzq_ptr; \
575 _zzq_args[0] = (unsigned int)(_zzq_request); \
576 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
577 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
578 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
579 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
580 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
581 _zzq_args[6] = (unsigned int)(_zzq_default); \
582 _zzq_ptr = _zzq_args; \
583 __asm__ volatile("mr 4,%1\n\t" \
584 "lwz 3, 24(4)\n\t" \
585 __SPECIAL_INSTRUCTION_PREAMBLE \
586 /* %R3 = client_request ( %R4 ) */ \
587 "or 1,1,1\n\t" \
588 "mr %0,3" \
589 : "=b" (_zzq_result) \
590 : "b" (_zzq_ptr) \
591 : "r3", "r4", "cc", "memory"); \
592 _zzq_rlval = _zzq_result; \
593 }
594
595#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
596 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
597 register unsigned int __addr; \
598 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
599 /* %R3 = guest_NRADDR */ \
600 "or 2,2,2\n\t" \
601 "mr %0,3" \
602 : "=b" (__addr) \
603 : \
604 : "r3", "cc", "memory" \
605 ); \
606 _zzq_orig->nraddr = __addr; \
607 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
608 /* %R3 = guest_NRADDR_GPR2 */ \
609 "or 4,4,4\n\t" \
610 "mr %0,3" \
611 : "=b" (__addr) \
612 : \
613 : "r3", "cc", "memory" \
614 ); \
615 _zzq_orig->r2 = __addr; \
616 }
617
618#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
619 __SPECIAL_INSTRUCTION_PREAMBLE \
620 /* branch-and-link-to-noredir *%R11 */ \
621 "or 3,3,3\n\t"
622
623#endif /* PLAT_ppc32_aix5 */
624
625/* ------------------------ ppc64-aix5 ------------------------- */
626
627#if defined(PLAT_ppc64_aix5)
628
629typedef
630 struct {
631 unsigned long long int nraddr; /* where's the code? */
632 unsigned long long int r2; /* what tocptr do we need? */
633 }
634 OrigFn;
635
636#define __SPECIAL_INSTRUCTION_PREAMBLE \
637 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
638 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
639
640#define VALGRIND_DO_CLIENT_REQUEST( \
641 _zzq_rlval, _zzq_default, _zzq_request, \
642 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
643 \
644 { unsigned long long int _zzq_args[7]; \
645 register unsigned long long int _zzq_result; \
646 register unsigned long long int* _zzq_ptr; \
647 _zzq_args[0] = (unsigned int long long)(_zzq_request); \
648 _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
649 _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
650 _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
651 _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
652 _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
653 _zzq_args[6] = (unsigned int long long)(_zzq_default); \
654 _zzq_ptr = _zzq_args; \
655 __asm__ volatile("mr 4,%1\n\t" \
656 "ld 3, 48(4)\n\t" \
657 __SPECIAL_INSTRUCTION_PREAMBLE \
658 /* %R3 = client_request ( %R4 ) */ \
659 "or 1,1,1\n\t" \
660 "mr %0,3" \
661 : "=b" (_zzq_result) \
662 : "b" (_zzq_ptr) \
663 : "r3", "r4", "cc", "memory"); \
664 _zzq_rlval = _zzq_result; \
665 }
666
667#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
668 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
669 register unsigned long long int __addr; \
670 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
671 /* %R3 = guest_NRADDR */ \
672 "or 2,2,2\n\t" \
673 "mr %0,3" \
674 : "=b" (__addr) \
675 : \
676 : "r3", "cc", "memory" \
677 ); \
678 _zzq_orig->nraddr = __addr; \
679 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
680 /* %R3 = guest_NRADDR_GPR2 */ \
681 "or 4,4,4\n\t" \
682 "mr %0,3" \
683 : "=b" (__addr) \
684 : \
685 : "r3", "cc", "memory" \
686 ); \
687 _zzq_orig->r2 = __addr; \
688 }
689
690#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
691 __SPECIAL_INSTRUCTION_PREAMBLE \
692 /* branch-and-link-to-noredir *%R11 */ \
693 "or 3,3,3\n\t"
694
695#endif /* PLAT_ppc64_aix5 */
696
697/* Insert assembly code for other platforms here... */
njn26aba4d2005-05-16 13:31:23 +0000698
sewardj37091fb2002-11-16 11:06:50 +0000699#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +0000700
nethercote69d9c462004-10-26 13:00:12 +0000701
njn30d76c62005-06-18 15:07:39 +0000702/* ------------------------------------------------------------------ */
sewardjf5c1a7f2006-10-17 01:32:48 +0000703/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
sewardj0ec07f32006-01-12 12:32:32 +0000704/* ugly. It's the least-worst tradeoff I can think of. */
705/* ------------------------------------------------------------------ */
706
707/* This section defines magic (a.k.a appalling-hack) macros for doing
708 guaranteed-no-redirection macros, so as to get from function
709 wrappers to the functions they are wrapping. The whole point is to
710 construct standard call sequences, but to do the call itself with a
711 special no-redirect call pseudo-instruction that the JIT
712 understands and handles specially. This section is long and
713 repetitious, and I can't see a way to make it shorter.
714
715 The naming scheme is as follows:
716
717 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
718
719 'W' stands for "word" and 'v' for "void". Hence there are
720 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
721 and for each, the possibility of returning a word-typed result, or
722 no result.
723*/
724
725/* Use these to write the name of your wrapper. NOTE: duplicates
726 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
727
njn5f5ef2a2009-05-11 08:01:09 +0000728/* Use an extra level of macroisation so as to ensure the soname/fnname
729 args are fully macro-expanded before pasting them together. */
730#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
731
sewardj0ec07f32006-01-12 12:32:32 +0000732#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
njn5f5ef2a2009-05-11 08:01:09 +0000733 VG_CONCAT4(_vgwZU_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000734
735#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
njn5f5ef2a2009-05-11 08:01:09 +0000736 VG_CONCAT4(_vgwZZ_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000737
sewardjd68ac3e2006-01-20 14:31:57 +0000738/* Use this macro from within a wrapper function to collect the
739 context (address and possibly other info) of the original function.
740 Once you have that you can then use it in one of the CALL_FN_
741 macros. The type of the argument _lval is OrigFn. */
742#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +0000743
744/* Derivatives of the main macros below, for calling functions
745 returning void. */
746
747#define CALL_FN_v_v(fnptr) \
748 do { volatile unsigned long _junk; \
749 CALL_FN_W_v(_junk,fnptr); } while (0)
750
751#define CALL_FN_v_W(fnptr, arg1) \
752 do { volatile unsigned long _junk; \
753 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
754
755#define CALL_FN_v_WW(fnptr, arg1,arg2) \
756 do { volatile unsigned long _junk; \
757 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
758
sewardj5ce4b152006-03-11 12:57:41 +0000759#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
760 do { volatile unsigned long _junk; \
761 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
762
njn2b5f0a92009-05-19 01:24:50 +0000763#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
764 do { volatile unsigned long _junk; \
765 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
766
767#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
768 do { volatile unsigned long _junk; \
769 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
770
771#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
772 do { volatile unsigned long _junk; \
773 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
774
775#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
776 do { volatile unsigned long _junk; \
777 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
778
njnf76d27a2009-05-28 01:53:07 +0000779/* ------------------------- x86-{linux,darwin} ---------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000780
njnf76d27a2009-05-28 01:53:07 +0000781#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
sewardj0ec07f32006-01-12 12:32:32 +0000782
783/* These regs are trashed by the hidden call. No need to mention eax
784 as gcc can already see that, plus causes gcc to bomb. */
785#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
786
787/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
788 long) == 4. */
789
sewardj66226cc2006-01-20 15:46:46 +0000790#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +0000791 do { \
sewardj66226cc2006-01-20 15:46:46 +0000792 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000793 volatile unsigned long _argvec[1]; \
794 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000795 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000796 __asm__ volatile( \
797 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
798 VALGRIND_CALL_NOREDIR_EAX \
799 : /*out*/ "=a" (_res) \
800 : /*in*/ "a" (&_argvec[0]) \
801 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
802 ); \
803 lval = (__typeof__(lval)) _res; \
804 } while (0)
805
sewardj66226cc2006-01-20 15:46:46 +0000806#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +0000807 do { \
sewardj66226cc2006-01-20 15:46:46 +0000808 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000809 volatile unsigned long _argvec[2]; \
810 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000811 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000812 _argvec[1] = (unsigned long)(arg1); \
813 __asm__ volatile( \
814 "pushl 4(%%eax)\n\t" \
815 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
816 VALGRIND_CALL_NOREDIR_EAX \
817 "addl $4, %%esp\n" \
818 : /*out*/ "=a" (_res) \
819 : /*in*/ "a" (&_argvec[0]) \
820 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
821 ); \
822 lval = (__typeof__(lval)) _res; \
823 } while (0)
824
sewardj66226cc2006-01-20 15:46:46 +0000825#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +0000826 do { \
sewardj66226cc2006-01-20 15:46:46 +0000827 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000828 volatile unsigned long _argvec[3]; \
829 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000830 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000831 _argvec[1] = (unsigned long)(arg1); \
832 _argvec[2] = (unsigned long)(arg2); \
833 __asm__ volatile( \
834 "pushl 8(%%eax)\n\t" \
835 "pushl 4(%%eax)\n\t" \
836 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
837 VALGRIND_CALL_NOREDIR_EAX \
838 "addl $8, %%esp\n" \
839 : /*out*/ "=a" (_res) \
840 : /*in*/ "a" (&_argvec[0]) \
841 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
842 ); \
843 lval = (__typeof__(lval)) _res; \
844 } while (0)
845
sewardj9e8b07a2006-02-18 21:13:29 +0000846#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
847 do { \
848 volatile OrigFn _orig = (orig); \
849 volatile unsigned long _argvec[4]; \
850 volatile unsigned long _res; \
851 _argvec[0] = (unsigned long)_orig.nraddr; \
852 _argvec[1] = (unsigned long)(arg1); \
853 _argvec[2] = (unsigned long)(arg2); \
854 _argvec[3] = (unsigned long)(arg3); \
855 __asm__ volatile( \
856 "pushl 12(%%eax)\n\t" \
857 "pushl 8(%%eax)\n\t" \
858 "pushl 4(%%eax)\n\t" \
859 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
860 VALGRIND_CALL_NOREDIR_EAX \
861 "addl $12, %%esp\n" \
862 : /*out*/ "=a" (_res) \
863 : /*in*/ "a" (&_argvec[0]) \
864 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
865 ); \
866 lval = (__typeof__(lval)) _res; \
867 } while (0)
868
sewardj66226cc2006-01-20 15:46:46 +0000869#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
sewardj0ec07f32006-01-12 12:32:32 +0000870 do { \
sewardj66226cc2006-01-20 15:46:46 +0000871 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000872 volatile unsigned long _argvec[5]; \
873 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000874 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000875 _argvec[1] = (unsigned long)(arg1); \
876 _argvec[2] = (unsigned long)(arg2); \
877 _argvec[3] = (unsigned long)(arg3); \
878 _argvec[4] = (unsigned long)(arg4); \
879 __asm__ volatile( \
880 "pushl 16(%%eax)\n\t" \
881 "pushl 12(%%eax)\n\t" \
882 "pushl 8(%%eax)\n\t" \
883 "pushl 4(%%eax)\n\t" \
884 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
885 VALGRIND_CALL_NOREDIR_EAX \
886 "addl $16, %%esp\n" \
887 : /*out*/ "=a" (_res) \
888 : /*in*/ "a" (&_argvec[0]) \
889 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
890 ); \
891 lval = (__typeof__(lval)) _res; \
892 } while (0)
893
sewardj66226cc2006-01-20 15:46:46 +0000894#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000895 do { \
sewardj66226cc2006-01-20 15:46:46 +0000896 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000897 volatile unsigned long _argvec[6]; \
898 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000899 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000900 _argvec[1] = (unsigned long)(arg1); \
901 _argvec[2] = (unsigned long)(arg2); \
902 _argvec[3] = (unsigned long)(arg3); \
903 _argvec[4] = (unsigned long)(arg4); \
904 _argvec[5] = (unsigned long)(arg5); \
905 __asm__ volatile( \
906 "pushl 20(%%eax)\n\t" \
907 "pushl 16(%%eax)\n\t" \
908 "pushl 12(%%eax)\n\t" \
909 "pushl 8(%%eax)\n\t" \
910 "pushl 4(%%eax)\n\t" \
911 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
912 VALGRIND_CALL_NOREDIR_EAX \
913 "addl $20, %%esp\n" \
914 : /*out*/ "=a" (_res) \
915 : /*in*/ "a" (&_argvec[0]) \
916 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
917 ); \
918 lval = (__typeof__(lval)) _res; \
919 } while (0)
920
sewardj66226cc2006-01-20 15:46:46 +0000921#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +0000922 do { \
sewardj66226cc2006-01-20 15:46:46 +0000923 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000924 volatile unsigned long _argvec[7]; \
925 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000926 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000927 _argvec[1] = (unsigned long)(arg1); \
928 _argvec[2] = (unsigned long)(arg2); \
929 _argvec[3] = (unsigned long)(arg3); \
930 _argvec[4] = (unsigned long)(arg4); \
931 _argvec[5] = (unsigned long)(arg5); \
932 _argvec[6] = (unsigned long)(arg6); \
933 __asm__ volatile( \
934 "pushl 24(%%eax)\n\t" \
935 "pushl 20(%%eax)\n\t" \
936 "pushl 16(%%eax)\n\t" \
937 "pushl 12(%%eax)\n\t" \
938 "pushl 8(%%eax)\n\t" \
939 "pushl 4(%%eax)\n\t" \
940 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
941 VALGRIND_CALL_NOREDIR_EAX \
942 "addl $24, %%esp\n" \
943 : /*out*/ "=a" (_res) \
944 : /*in*/ "a" (&_argvec[0]) \
945 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
946 ); \
947 lval = (__typeof__(lval)) _res; \
948 } while (0)
949
sewardj66226cc2006-01-20 15:46:46 +0000950#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
951 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +0000952 do { \
sewardj66226cc2006-01-20 15:46:46 +0000953 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000954 volatile unsigned long _argvec[8]; \
955 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000956 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000957 _argvec[1] = (unsigned long)(arg1); \
958 _argvec[2] = (unsigned long)(arg2); \
959 _argvec[3] = (unsigned long)(arg3); \
960 _argvec[4] = (unsigned long)(arg4); \
961 _argvec[5] = (unsigned long)(arg5); \
962 _argvec[6] = (unsigned long)(arg6); \
963 _argvec[7] = (unsigned long)(arg7); \
964 __asm__ volatile( \
965 "pushl 28(%%eax)\n\t" \
966 "pushl 24(%%eax)\n\t" \
967 "pushl 20(%%eax)\n\t" \
968 "pushl 16(%%eax)\n\t" \
969 "pushl 12(%%eax)\n\t" \
970 "pushl 8(%%eax)\n\t" \
971 "pushl 4(%%eax)\n\t" \
972 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
973 VALGRIND_CALL_NOREDIR_EAX \
974 "addl $28, %%esp\n" \
975 : /*out*/ "=a" (_res) \
976 : /*in*/ "a" (&_argvec[0]) \
977 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
978 ); \
979 lval = (__typeof__(lval)) _res; \
980 } while (0)
981
sewardj66226cc2006-01-20 15:46:46 +0000982#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
983 arg7,arg8) \
sewardj0ec07f32006-01-12 12:32:32 +0000984 do { \
sewardj66226cc2006-01-20 15:46:46 +0000985 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000986 volatile unsigned long _argvec[9]; \
987 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000988 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000989 _argvec[1] = (unsigned long)(arg1); \
990 _argvec[2] = (unsigned long)(arg2); \
991 _argvec[3] = (unsigned long)(arg3); \
992 _argvec[4] = (unsigned long)(arg4); \
993 _argvec[5] = (unsigned long)(arg5); \
994 _argvec[6] = (unsigned long)(arg6); \
995 _argvec[7] = (unsigned long)(arg7); \
996 _argvec[8] = (unsigned long)(arg8); \
997 __asm__ volatile( \
998 "pushl 32(%%eax)\n\t" \
999 "pushl 28(%%eax)\n\t" \
1000 "pushl 24(%%eax)\n\t" \
1001 "pushl 20(%%eax)\n\t" \
1002 "pushl 16(%%eax)\n\t" \
1003 "pushl 12(%%eax)\n\t" \
1004 "pushl 8(%%eax)\n\t" \
1005 "pushl 4(%%eax)\n\t" \
1006 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1007 VALGRIND_CALL_NOREDIR_EAX \
1008 "addl $32, %%esp\n" \
1009 : /*out*/ "=a" (_res) \
1010 : /*in*/ "a" (&_argvec[0]) \
1011 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1012 ); \
1013 lval = (__typeof__(lval)) _res; \
1014 } while (0)
1015
sewardj45fa5b02006-03-09 19:06:23 +00001016#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1017 arg7,arg8,arg9) \
1018 do { \
1019 volatile OrigFn _orig = (orig); \
1020 volatile unsigned long _argvec[10]; \
1021 volatile unsigned long _res; \
1022 _argvec[0] = (unsigned long)_orig.nraddr; \
1023 _argvec[1] = (unsigned long)(arg1); \
1024 _argvec[2] = (unsigned long)(arg2); \
1025 _argvec[3] = (unsigned long)(arg3); \
1026 _argvec[4] = (unsigned long)(arg4); \
1027 _argvec[5] = (unsigned long)(arg5); \
1028 _argvec[6] = (unsigned long)(arg6); \
1029 _argvec[7] = (unsigned long)(arg7); \
1030 _argvec[8] = (unsigned long)(arg8); \
1031 _argvec[9] = (unsigned long)(arg9); \
1032 __asm__ volatile( \
1033 "pushl 36(%%eax)\n\t" \
1034 "pushl 32(%%eax)\n\t" \
1035 "pushl 28(%%eax)\n\t" \
1036 "pushl 24(%%eax)\n\t" \
1037 "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 \
1044 "addl $36, %%esp\n" \
1045 : /*out*/ "=a" (_res) \
1046 : /*in*/ "a" (&_argvec[0]) \
1047 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1048 ); \
1049 lval = (__typeof__(lval)) _res; \
1050 } while (0)
1051
1052#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1053 arg7,arg8,arg9,arg10) \
1054 do { \
1055 volatile OrigFn _orig = (orig); \
1056 volatile unsigned long _argvec[11]; \
1057 volatile unsigned long _res; \
1058 _argvec[0] = (unsigned long)_orig.nraddr; \
1059 _argvec[1] = (unsigned long)(arg1); \
1060 _argvec[2] = (unsigned long)(arg2); \
1061 _argvec[3] = (unsigned long)(arg3); \
1062 _argvec[4] = (unsigned long)(arg4); \
1063 _argvec[5] = (unsigned long)(arg5); \
1064 _argvec[6] = (unsigned long)(arg6); \
1065 _argvec[7] = (unsigned long)(arg7); \
1066 _argvec[8] = (unsigned long)(arg8); \
1067 _argvec[9] = (unsigned long)(arg9); \
1068 _argvec[10] = (unsigned long)(arg10); \
1069 __asm__ volatile( \
1070 "pushl 40(%%eax)\n\t" \
1071 "pushl 36(%%eax)\n\t" \
1072 "pushl 32(%%eax)\n\t" \
1073 "pushl 28(%%eax)\n\t" \
1074 "pushl 24(%%eax)\n\t" \
1075 "pushl 20(%%eax)\n\t" \
1076 "pushl 16(%%eax)\n\t" \
1077 "pushl 12(%%eax)\n\t" \
1078 "pushl 8(%%eax)\n\t" \
1079 "pushl 4(%%eax)\n\t" \
1080 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1081 VALGRIND_CALL_NOREDIR_EAX \
1082 "addl $40, %%esp\n" \
1083 : /*out*/ "=a" (_res) \
1084 : /*in*/ "a" (&_argvec[0]) \
1085 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1086 ); \
1087 lval = (__typeof__(lval)) _res; \
1088 } while (0)
1089
sewardj5ce4b152006-03-11 12:57:41 +00001090#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1091 arg6,arg7,arg8,arg9,arg10, \
1092 arg11) \
1093 do { \
1094 volatile OrigFn _orig = (orig); \
1095 volatile unsigned long _argvec[12]; \
1096 volatile unsigned long _res; \
1097 _argvec[0] = (unsigned long)_orig.nraddr; \
1098 _argvec[1] = (unsigned long)(arg1); \
1099 _argvec[2] = (unsigned long)(arg2); \
1100 _argvec[3] = (unsigned long)(arg3); \
1101 _argvec[4] = (unsigned long)(arg4); \
1102 _argvec[5] = (unsigned long)(arg5); \
1103 _argvec[6] = (unsigned long)(arg6); \
1104 _argvec[7] = (unsigned long)(arg7); \
1105 _argvec[8] = (unsigned long)(arg8); \
1106 _argvec[9] = (unsigned long)(arg9); \
1107 _argvec[10] = (unsigned long)(arg10); \
1108 _argvec[11] = (unsigned long)(arg11); \
1109 __asm__ volatile( \
1110 "pushl 44(%%eax)\n\t" \
1111 "pushl 40(%%eax)\n\t" \
1112 "pushl 36(%%eax)\n\t" \
1113 "pushl 32(%%eax)\n\t" \
1114 "pushl 28(%%eax)\n\t" \
1115 "pushl 24(%%eax)\n\t" \
1116 "pushl 20(%%eax)\n\t" \
1117 "pushl 16(%%eax)\n\t" \
1118 "pushl 12(%%eax)\n\t" \
1119 "pushl 8(%%eax)\n\t" \
1120 "pushl 4(%%eax)\n\t" \
1121 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1122 VALGRIND_CALL_NOREDIR_EAX \
1123 "addl $44, %%esp\n" \
1124 : /*out*/ "=a" (_res) \
1125 : /*in*/ "a" (&_argvec[0]) \
1126 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1127 ); \
1128 lval = (__typeof__(lval)) _res; \
1129 } while (0)
1130
sewardj66226cc2006-01-20 15:46:46 +00001131#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1132 arg6,arg7,arg8,arg9,arg10, \
1133 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +00001134 do { \
sewardj66226cc2006-01-20 15:46:46 +00001135 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001136 volatile unsigned long _argvec[13]; \
1137 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001138 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001139 _argvec[1] = (unsigned long)(arg1); \
1140 _argvec[2] = (unsigned long)(arg2); \
1141 _argvec[3] = (unsigned long)(arg3); \
1142 _argvec[4] = (unsigned long)(arg4); \
1143 _argvec[5] = (unsigned long)(arg5); \
1144 _argvec[6] = (unsigned long)(arg6); \
1145 _argvec[7] = (unsigned long)(arg7); \
1146 _argvec[8] = (unsigned long)(arg8); \
1147 _argvec[9] = (unsigned long)(arg9); \
1148 _argvec[10] = (unsigned long)(arg10); \
1149 _argvec[11] = (unsigned long)(arg11); \
1150 _argvec[12] = (unsigned long)(arg12); \
1151 __asm__ volatile( \
1152 "pushl 48(%%eax)\n\t" \
1153 "pushl 44(%%eax)\n\t" \
1154 "pushl 40(%%eax)\n\t" \
1155 "pushl 36(%%eax)\n\t" \
1156 "pushl 32(%%eax)\n\t" \
1157 "pushl 28(%%eax)\n\t" \
1158 "pushl 24(%%eax)\n\t" \
1159 "pushl 20(%%eax)\n\t" \
1160 "pushl 16(%%eax)\n\t" \
1161 "pushl 12(%%eax)\n\t" \
1162 "pushl 8(%%eax)\n\t" \
1163 "pushl 4(%%eax)\n\t" \
1164 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1165 VALGRIND_CALL_NOREDIR_EAX \
1166 "addl $48, %%esp\n" \
1167 : /*out*/ "=a" (_res) \
1168 : /*in*/ "a" (&_argvec[0]) \
1169 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1170 ); \
1171 lval = (__typeof__(lval)) _res; \
1172 } while (0)
1173
njnf76d27a2009-05-28 01:53:07 +00001174#endif /* PLAT_x86_linux || PLAT_x86_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001175
njnf76d27a2009-05-28 01:53:07 +00001176/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001177
njnf76d27a2009-05-28 01:53:07 +00001178#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardj0ec07f32006-01-12 12:32:32 +00001179
1180/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1181
1182/* These regs are trashed by the hidden call. */
1183#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1184 "rdi", "r8", "r9", "r10", "r11"
1185
sewardjdfa55cf2010-10-06 22:07:06 +00001186/* This is all pretty complex. It's so as to make stack unwinding
1187 work reliably. See bug 243270. The basic problem is the sub and
1188 add of 128 of %rsp in all of the following macros. If gcc believes
1189 the CFA is in %rsp, then unwinding may fail, because what's at the
1190 CFA is not what gcc "expected" when it constructs the CFIs for the
1191 places where the macros are instantiated.
1192
1193 But we can't just add a CFI annotation to increase the CFA offset
1194 by 128, to match the sub of 128 from %rsp, because we don't know
1195 whether gcc has chosen %rsp as the CFA at that point, or whether it
1196 has chosen some other register (eg, %rbp). In the latter case,
1197 adding a CFI annotation to change the CFA offset is simply wrong.
1198
1199 So the solution is to get hold of the CFA using
1200 __builtin_frame_address(0), put it in a known register, and add a
1201 CFI annotation to say what the register is. We choose %rbp for
1202 this (perhaps perversely), because:
1203
1204 (1) %rbp is already subject to unwinding. If a new register was
1205 chosen then the unwinder would have to unwind it in all stack
1206 traces, which is expensive, and
1207
1208 (2) %rbp is already subject to precise exception updates in the
1209 JIT. If a new register was chosen, we'd have to have precise
1210 exceptions for it too, which reduces performance of the
1211 generated code.
1212
1213 However .. one extra complication. We can't just whack the result
1214 of __builtin_frame_address(0) into %rbp and then add %rbp to the
1215 list of trashed registers at the end of the inline assembly
1216 fragments; gcc won't allow %rbp to appear in that list. Hence
1217 instead we need to stash %rbp in %r15 for the duration of the asm,
1218 and say that %r15 is trashed instead. gcc seems happy to go with
1219 that.
1220
1221 Oh .. and this all needs to be conditionalised so that it is
1222 unchanged from before this commit, when compiled with older gccs
1223 that don't support __builtin_frame_address.
1224*/
1225#if HAVE_BUILTIN_FRAME_ADDRESS
1226# define __FRAME_POINTER \
1227 ,"r"(__builtin_frame_address(0))
1228# define VALGRIND_CFI_PROLOGUE \
1229 ".cfi_remember_state\n\t" \
1230 "movq %%rbp, %%r15\n\t" \
1231 "movq %0, %%rbp\n\t" \
1232 ".cfi_def_cfa rbp, 0\n\t"
1233# define VALGRIND_CFI_EPILOGUE \
1234 "movq %%r15, %%rbp\n\t" \
1235 ".cfi_restore_state\n\t"
1236#else
1237# define __FRAME_POINTER
1238# define VALGRIND_CFI_PROLOGUE
1239# define VALGRIND_CFI_EPILOGUE
1240#endif
1241
1242
sewardj0ec07f32006-01-12 12:32:32 +00001243/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1244 long) == 8. */
1245
sewardja07c2e12007-11-09 23:09:50 +00001246/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1247 macros. In order not to trash the stack redzone, we need to drop
1248 %rsp by 128 before the hidden call, and restore afterwards. The
1249 nastyness is that it is only by luck that the stack still appears
1250 to be unwindable during the hidden call - since then the behaviour
1251 of any routine using this macro does not match what the CFI data
1252 says. Sigh.
1253
1254 Why is this important? Imagine that a wrapper has a stack
1255 allocated local, and passes to the hidden call, a pointer to it.
1256 Because gcc does not know about the hidden call, it may allocate
1257 that local in the redzone. Unfortunately the hidden call may then
1258 trash it before it comes to use it. So we must step clear of the
1259 redzone, for the duration of the hidden call, to make it safe.
1260
1261 Probably the same problem afflicts the other redzone-style ABIs too
1262 (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
1263 self describing (none of this CFI nonsense) so at least messing
1264 with the stack pointer doesn't give a danger of non-unwindable
1265 stack. */
1266
sewardjc8858442006-01-20 15:17:20 +00001267#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001268 do { \
sewardjc8858442006-01-20 15:17:20 +00001269 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001270 volatile unsigned long _argvec[1]; \
1271 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001272 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001273 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001274 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001275 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001276 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1277 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001278 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001279 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001280 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001281 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1282 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001283 ); \
1284 lval = (__typeof__(lval)) _res; \
1285 } while (0)
1286
sewardjc8858442006-01-20 15:17:20 +00001287#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001288 do { \
sewardjc8858442006-01-20 15:17:20 +00001289 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001290 volatile unsigned long _argvec[2]; \
1291 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001292 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001293 _argvec[1] = (unsigned long)(arg1); \
1294 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001295 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001296 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001297 "movq 8(%%rax), %%rdi\n\t" \
1298 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1299 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001300 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001301 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001302 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001303 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1304 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001305 ); \
1306 lval = (__typeof__(lval)) _res; \
1307 } while (0)
1308
sewardjc8858442006-01-20 15:17:20 +00001309#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001310 do { \
sewardjc8858442006-01-20 15:17:20 +00001311 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001312 volatile unsigned long _argvec[3]; \
1313 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001314 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001315 _argvec[1] = (unsigned long)(arg1); \
1316 _argvec[2] = (unsigned long)(arg2); \
1317 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001318 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001319 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001320 "movq 16(%%rax), %%rsi\n\t" \
1321 "movq 8(%%rax), %%rdi\n\t" \
1322 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1323 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001324 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001325 VALGRIND_CFI_EPILOGUE \
sewardj0ec07f32006-01-12 12:32:32 +00001326 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001327 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1328 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardj0ec07f32006-01-12 12:32:32 +00001329 ); \
1330 lval = (__typeof__(lval)) _res; \
1331 } while (0)
1332
sewardja50f9dc2006-03-11 16:19:14 +00001333#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1334 do { \
1335 volatile OrigFn _orig = (orig); \
1336 volatile unsigned long _argvec[4]; \
1337 volatile unsigned long _res; \
1338 _argvec[0] = (unsigned long)_orig.nraddr; \
1339 _argvec[1] = (unsigned long)(arg1); \
1340 _argvec[2] = (unsigned long)(arg2); \
1341 _argvec[3] = (unsigned long)(arg3); \
1342 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001343 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001344 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001345 "movq 24(%%rax), %%rdx\n\t" \
1346 "movq 16(%%rax), %%rsi\n\t" \
1347 "movq 8(%%rax), %%rdi\n\t" \
1348 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1349 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001350 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001351 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001352 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001353 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1354 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001355 ); \
1356 lval = (__typeof__(lval)) _res; \
1357 } while (0)
1358
1359#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1360 do { \
1361 volatile OrigFn _orig = (orig); \
1362 volatile unsigned long _argvec[5]; \
1363 volatile unsigned long _res; \
1364 _argvec[0] = (unsigned long)_orig.nraddr; \
1365 _argvec[1] = (unsigned long)(arg1); \
1366 _argvec[2] = (unsigned long)(arg2); \
1367 _argvec[3] = (unsigned long)(arg3); \
1368 _argvec[4] = (unsigned long)(arg4); \
1369 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001370 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001371 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001372 "movq 32(%%rax), %%rcx\n\t" \
1373 "movq 24(%%rax), %%rdx\n\t" \
1374 "movq 16(%%rax), %%rsi\n\t" \
1375 "movq 8(%%rax), %%rdi\n\t" \
1376 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1377 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001378 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001379 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001380 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001381 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1382 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001383 ); \
1384 lval = (__typeof__(lval)) _res; \
1385 } while (0)
1386
1387#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1388 do { \
1389 volatile OrigFn _orig = (orig); \
1390 volatile unsigned long _argvec[6]; \
1391 volatile unsigned long _res; \
1392 _argvec[0] = (unsigned long)_orig.nraddr; \
1393 _argvec[1] = (unsigned long)(arg1); \
1394 _argvec[2] = (unsigned long)(arg2); \
1395 _argvec[3] = (unsigned long)(arg3); \
1396 _argvec[4] = (unsigned long)(arg4); \
1397 _argvec[5] = (unsigned long)(arg5); \
1398 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001399 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001400 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001401 "movq 40(%%rax), %%r8\n\t" \
1402 "movq 32(%%rax), %%rcx\n\t" \
1403 "movq 24(%%rax), %%rdx\n\t" \
1404 "movq 16(%%rax), %%rsi\n\t" \
1405 "movq 8(%%rax), %%rdi\n\t" \
1406 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1407 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001408 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001409 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001410 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001411 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1412 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001413 ); \
1414 lval = (__typeof__(lval)) _res; \
1415 } while (0)
1416
1417#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1418 do { \
1419 volatile OrigFn _orig = (orig); \
1420 volatile unsigned long _argvec[7]; \
1421 volatile unsigned long _res; \
1422 _argvec[0] = (unsigned long)_orig.nraddr; \
1423 _argvec[1] = (unsigned long)(arg1); \
1424 _argvec[2] = (unsigned long)(arg2); \
1425 _argvec[3] = (unsigned long)(arg3); \
1426 _argvec[4] = (unsigned long)(arg4); \
1427 _argvec[5] = (unsigned long)(arg5); \
1428 _argvec[6] = (unsigned long)(arg6); \
1429 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001430 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001431 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001432 "movq 48(%%rax), %%r9\n\t" \
1433 "movq 40(%%rax), %%r8\n\t" \
1434 "movq 32(%%rax), %%rcx\n\t" \
1435 "movq 24(%%rax), %%rdx\n\t" \
1436 "movq 16(%%rax), %%rsi\n\t" \
1437 "movq 8(%%rax), %%rdi\n\t" \
1438 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1439 VALGRIND_CALL_NOREDIR_RAX \
bart2823aac2010-09-05 12:10:25 +00001440 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001441 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001442 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001443 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1444 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001445 ); \
1446 lval = (__typeof__(lval)) _res; \
1447 } while (0)
1448
1449#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1450 arg7) \
1451 do { \
1452 volatile OrigFn _orig = (orig); \
1453 volatile unsigned long _argvec[8]; \
1454 volatile unsigned long _res; \
1455 _argvec[0] = (unsigned long)_orig.nraddr; \
1456 _argvec[1] = (unsigned long)(arg1); \
1457 _argvec[2] = (unsigned long)(arg2); \
1458 _argvec[3] = (unsigned long)(arg3); \
1459 _argvec[4] = (unsigned long)(arg4); \
1460 _argvec[5] = (unsigned long)(arg5); \
1461 _argvec[6] = (unsigned long)(arg6); \
1462 _argvec[7] = (unsigned long)(arg7); \
1463 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001464 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001465 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001466 "pushq 56(%%rax)\n\t" \
1467 "movq 48(%%rax), %%r9\n\t" \
1468 "movq 40(%%rax), %%r8\n\t" \
1469 "movq 32(%%rax), %%rcx\n\t" \
1470 "movq 24(%%rax), %%rdx\n\t" \
1471 "movq 16(%%rax), %%rsi\n\t" \
1472 "movq 8(%%rax), %%rdi\n\t" \
1473 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1474 VALGRIND_CALL_NOREDIR_RAX \
1475 "addq $8, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001476 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001477 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001478 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001479 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1480 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001481 ); \
1482 lval = (__typeof__(lval)) _res; \
1483 } while (0)
1484
1485#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1486 arg7,arg8) \
1487 do { \
1488 volatile OrigFn _orig = (orig); \
1489 volatile unsigned long _argvec[9]; \
1490 volatile unsigned long _res; \
1491 _argvec[0] = (unsigned long)_orig.nraddr; \
1492 _argvec[1] = (unsigned long)(arg1); \
1493 _argvec[2] = (unsigned long)(arg2); \
1494 _argvec[3] = (unsigned long)(arg3); \
1495 _argvec[4] = (unsigned long)(arg4); \
1496 _argvec[5] = (unsigned long)(arg5); \
1497 _argvec[6] = (unsigned long)(arg6); \
1498 _argvec[7] = (unsigned long)(arg7); \
1499 _argvec[8] = (unsigned long)(arg8); \
1500 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001501 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001502 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001503 "pushq 64(%%rax)\n\t" \
1504 "pushq 56(%%rax)\n\t" \
1505 "movq 48(%%rax), %%r9\n\t" \
1506 "movq 40(%%rax), %%r8\n\t" \
1507 "movq 32(%%rax), %%rcx\n\t" \
1508 "movq 24(%%rax), %%rdx\n\t" \
1509 "movq 16(%%rax), %%rsi\n\t" \
1510 "movq 8(%%rax), %%rdi\n\t" \
1511 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1512 VALGRIND_CALL_NOREDIR_RAX \
1513 "addq $16, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001514 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001515 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001516 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001517 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1518 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001519 ); \
1520 lval = (__typeof__(lval)) _res; \
1521 } while (0)
1522
1523#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1524 arg7,arg8,arg9) \
1525 do { \
1526 volatile OrigFn _orig = (orig); \
1527 volatile unsigned long _argvec[10]; \
1528 volatile unsigned long _res; \
1529 _argvec[0] = (unsigned long)_orig.nraddr; \
1530 _argvec[1] = (unsigned long)(arg1); \
1531 _argvec[2] = (unsigned long)(arg2); \
1532 _argvec[3] = (unsigned long)(arg3); \
1533 _argvec[4] = (unsigned long)(arg4); \
1534 _argvec[5] = (unsigned long)(arg5); \
1535 _argvec[6] = (unsigned long)(arg6); \
1536 _argvec[7] = (unsigned long)(arg7); \
1537 _argvec[8] = (unsigned long)(arg8); \
1538 _argvec[9] = (unsigned long)(arg9); \
1539 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001540 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001541 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001542 "pushq 72(%%rax)\n\t" \
1543 "pushq 64(%%rax)\n\t" \
1544 "pushq 56(%%rax)\n\t" \
1545 "movq 48(%%rax), %%r9\n\t" \
1546 "movq 40(%%rax), %%r8\n\t" \
1547 "movq 32(%%rax), %%rcx\n\t" \
1548 "movq 24(%%rax), %%rdx\n\t" \
1549 "movq 16(%%rax), %%rsi\n\t" \
1550 "movq 8(%%rax), %%rdi\n\t" \
1551 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1552 VALGRIND_CALL_NOREDIR_RAX \
1553 "addq $24, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001554 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001555 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001556 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001557 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1558 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001559 ); \
1560 lval = (__typeof__(lval)) _res; \
1561 } while (0)
1562
1563#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1564 arg7,arg8,arg9,arg10) \
1565 do { \
1566 volatile OrigFn _orig = (orig); \
1567 volatile unsigned long _argvec[11]; \
1568 volatile unsigned long _res; \
1569 _argvec[0] = (unsigned long)_orig.nraddr; \
1570 _argvec[1] = (unsigned long)(arg1); \
1571 _argvec[2] = (unsigned long)(arg2); \
1572 _argvec[3] = (unsigned long)(arg3); \
1573 _argvec[4] = (unsigned long)(arg4); \
1574 _argvec[5] = (unsigned long)(arg5); \
1575 _argvec[6] = (unsigned long)(arg6); \
1576 _argvec[7] = (unsigned long)(arg7); \
1577 _argvec[8] = (unsigned long)(arg8); \
1578 _argvec[9] = (unsigned long)(arg9); \
1579 _argvec[10] = (unsigned long)(arg10); \
1580 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001581 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001582 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001583 "pushq 80(%%rax)\n\t" \
1584 "pushq 72(%%rax)\n\t" \
1585 "pushq 64(%%rax)\n\t" \
1586 "pushq 56(%%rax)\n\t" \
1587 "movq 48(%%rax), %%r9\n\t" \
1588 "movq 40(%%rax), %%r8\n\t" \
1589 "movq 32(%%rax), %%rcx\n\t" \
1590 "movq 24(%%rax), %%rdx\n\t" \
1591 "movq 16(%%rax), %%rsi\n\t" \
1592 "movq 8(%%rax), %%rdi\n\t" \
1593 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1594 VALGRIND_CALL_NOREDIR_RAX \
1595 "addq $32, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001596 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001597 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001598 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001599 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1600 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001601 ); \
1602 lval = (__typeof__(lval)) _res; \
1603 } while (0)
1604
1605#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1606 arg7,arg8,arg9,arg10,arg11) \
1607 do { \
1608 volatile OrigFn _orig = (orig); \
1609 volatile unsigned long _argvec[12]; \
1610 volatile unsigned long _res; \
1611 _argvec[0] = (unsigned long)_orig.nraddr; \
1612 _argvec[1] = (unsigned long)(arg1); \
1613 _argvec[2] = (unsigned long)(arg2); \
1614 _argvec[3] = (unsigned long)(arg3); \
1615 _argvec[4] = (unsigned long)(arg4); \
1616 _argvec[5] = (unsigned long)(arg5); \
1617 _argvec[6] = (unsigned long)(arg6); \
1618 _argvec[7] = (unsigned long)(arg7); \
1619 _argvec[8] = (unsigned long)(arg8); \
1620 _argvec[9] = (unsigned long)(arg9); \
1621 _argvec[10] = (unsigned long)(arg10); \
1622 _argvec[11] = (unsigned long)(arg11); \
1623 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001624 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001625 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001626 "pushq 88(%%rax)\n\t" \
1627 "pushq 80(%%rax)\n\t" \
1628 "pushq 72(%%rax)\n\t" \
1629 "pushq 64(%%rax)\n\t" \
1630 "pushq 56(%%rax)\n\t" \
1631 "movq 48(%%rax), %%r9\n\t" \
1632 "movq 40(%%rax), %%r8\n\t" \
1633 "movq 32(%%rax), %%rcx\n\t" \
1634 "movq 24(%%rax), %%rdx\n\t" \
1635 "movq 16(%%rax), %%rsi\n\t" \
1636 "movq 8(%%rax), %%rdi\n\t" \
1637 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1638 VALGRIND_CALL_NOREDIR_RAX \
1639 "addq $40, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001640 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001641 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001642 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001643 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1644 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001645 ); \
1646 lval = (__typeof__(lval)) _res; \
1647 } while (0)
1648
1649#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1650 arg7,arg8,arg9,arg10,arg11,arg12) \
1651 do { \
1652 volatile OrigFn _orig = (orig); \
1653 volatile unsigned long _argvec[13]; \
1654 volatile unsigned long _res; \
1655 _argvec[0] = (unsigned long)_orig.nraddr; \
1656 _argvec[1] = (unsigned long)(arg1); \
1657 _argvec[2] = (unsigned long)(arg2); \
1658 _argvec[3] = (unsigned long)(arg3); \
1659 _argvec[4] = (unsigned long)(arg4); \
1660 _argvec[5] = (unsigned long)(arg5); \
1661 _argvec[6] = (unsigned long)(arg6); \
1662 _argvec[7] = (unsigned long)(arg7); \
1663 _argvec[8] = (unsigned long)(arg8); \
1664 _argvec[9] = (unsigned long)(arg9); \
1665 _argvec[10] = (unsigned long)(arg10); \
1666 _argvec[11] = (unsigned long)(arg11); \
1667 _argvec[12] = (unsigned long)(arg12); \
1668 __asm__ volatile( \
sewardjdfa55cf2010-10-06 22:07:06 +00001669 VALGRIND_CFI_PROLOGUE \
sewardja07c2e12007-11-09 23:09:50 +00001670 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001671 "pushq 96(%%rax)\n\t" \
1672 "pushq 88(%%rax)\n\t" \
1673 "pushq 80(%%rax)\n\t" \
1674 "pushq 72(%%rax)\n\t" \
1675 "pushq 64(%%rax)\n\t" \
1676 "pushq 56(%%rax)\n\t" \
1677 "movq 48(%%rax), %%r9\n\t" \
1678 "movq 40(%%rax), %%r8\n\t" \
1679 "movq 32(%%rax), %%rcx\n\t" \
1680 "movq 24(%%rax), %%rdx\n\t" \
1681 "movq 16(%%rax), %%rsi\n\t" \
1682 "movq 8(%%rax), %%rdi\n\t" \
1683 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1684 VALGRIND_CALL_NOREDIR_RAX \
1685 "addq $48, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001686 "addq $128,%%rsp\n\t" \
sewardjdfa55cf2010-10-06 22:07:06 +00001687 VALGRIND_CFI_EPILOGUE \
sewardja50f9dc2006-03-11 16:19:14 +00001688 : /*out*/ "=a" (_res) \
sewardjdfa55cf2010-10-06 22:07:06 +00001689 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
1690 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \
sewardja50f9dc2006-03-11 16:19:14 +00001691 ); \
1692 lval = (__typeof__(lval)) _res; \
1693 } while (0)
1694
njnf76d27a2009-05-28 01:53:07 +00001695#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001696
sewardjf5c1a7f2006-10-17 01:32:48 +00001697/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00001698
sewardjf5c1a7f2006-10-17 01:32:48 +00001699#if defined(PLAT_ppc32_linux)
sewardj0ec07f32006-01-12 12:32:32 +00001700
sewardjead61df2006-03-12 13:39:15 +00001701/* This is useful for finding out about the on-stack stuff:
1702
1703 extern int f9 ( int,int,int,int,int,int,int,int,int );
1704 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1705 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1706 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1707
1708 int g9 ( void ) {
1709 return f9(11,22,33,44,55,66,77,88,99);
1710 }
1711 int g10 ( void ) {
1712 return f10(11,22,33,44,55,66,77,88,99,110);
1713 }
1714 int g11 ( void ) {
1715 return f11(11,22,33,44,55,66,77,88,99,110,121);
1716 }
1717 int g12 ( void ) {
1718 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1719 }
1720*/
1721
sewardj0ec07f32006-01-12 12:32:32 +00001722/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1723
1724/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00001725#define __CALLER_SAVED_REGS \
1726 "lr", "ctr", "xer", \
1727 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1728 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1729 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00001730
sewardjead61df2006-03-12 13:39:15 +00001731/* These CALL_FN_ macros assume that on ppc32-linux,
1732 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00001733
sewardj38de0992006-01-20 16:46:34 +00001734#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001735 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001736 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001737 volatile unsigned long _argvec[1]; \
1738 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001739 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001740 __asm__ volatile( \
1741 "mr 11,%1\n\t" \
1742 "lwz 11,0(11)\n\t" /* target->r11 */ \
1743 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1744 "mr %0,3" \
1745 : /*out*/ "=r" (_res) \
1746 : /*in*/ "r" (&_argvec[0]) \
1747 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1748 ); \
1749 lval = (__typeof__(lval)) _res; \
1750 } while (0)
1751
sewardj38de0992006-01-20 16:46:34 +00001752#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001753 do { \
sewardj38de0992006-01-20 16:46:34 +00001754 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001755 volatile unsigned long _argvec[2]; \
1756 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001757 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001758 _argvec[1] = (unsigned long)arg1; \
1759 __asm__ volatile( \
1760 "mr 11,%1\n\t" \
1761 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1762 "lwz 11,0(11)\n\t" /* target->r11 */ \
1763 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1764 "mr %0,3" \
1765 : /*out*/ "=r" (_res) \
1766 : /*in*/ "r" (&_argvec[0]) \
1767 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1768 ); \
1769 lval = (__typeof__(lval)) _res; \
1770 } while (0)
1771
sewardj38de0992006-01-20 16:46:34 +00001772#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001773 do { \
sewardj38de0992006-01-20 16:46:34 +00001774 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001775 volatile unsigned long _argvec[3]; \
1776 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001777 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001778 _argvec[1] = (unsigned long)arg1; \
1779 _argvec[2] = (unsigned long)arg2; \
1780 __asm__ volatile( \
1781 "mr 11,%1\n\t" \
1782 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1783 "lwz 4,8(11)\n\t" \
1784 "lwz 11,0(11)\n\t" /* target->r11 */ \
1785 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1786 "mr %0,3" \
1787 : /*out*/ "=r" (_res) \
1788 : /*in*/ "r" (&_argvec[0]) \
1789 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1790 ); \
1791 lval = (__typeof__(lval)) _res; \
1792 } while (0)
1793
sewardjead61df2006-03-12 13:39:15 +00001794#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1795 do { \
1796 volatile OrigFn _orig = (orig); \
1797 volatile unsigned long _argvec[4]; \
1798 volatile unsigned long _res; \
1799 _argvec[0] = (unsigned long)_orig.nraddr; \
1800 _argvec[1] = (unsigned long)arg1; \
1801 _argvec[2] = (unsigned long)arg2; \
1802 _argvec[3] = (unsigned long)arg3; \
1803 __asm__ volatile( \
1804 "mr 11,%1\n\t" \
1805 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1806 "lwz 4,8(11)\n\t" \
1807 "lwz 5,12(11)\n\t" \
1808 "lwz 11,0(11)\n\t" /* target->r11 */ \
1809 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1810 "mr %0,3" \
1811 : /*out*/ "=r" (_res) \
1812 : /*in*/ "r" (&_argvec[0]) \
1813 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1814 ); \
1815 lval = (__typeof__(lval)) _res; \
1816 } while (0)
1817
1818#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1819 do { \
1820 volatile OrigFn _orig = (orig); \
1821 volatile unsigned long _argvec[5]; \
1822 volatile unsigned long _res; \
1823 _argvec[0] = (unsigned long)_orig.nraddr; \
1824 _argvec[1] = (unsigned long)arg1; \
1825 _argvec[2] = (unsigned long)arg2; \
1826 _argvec[3] = (unsigned long)arg3; \
1827 _argvec[4] = (unsigned long)arg4; \
1828 __asm__ volatile( \
1829 "mr 11,%1\n\t" \
1830 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1831 "lwz 4,8(11)\n\t" \
1832 "lwz 5,12(11)\n\t" \
1833 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1834 "lwz 11,0(11)\n\t" /* target->r11 */ \
1835 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1836 "mr %0,3" \
1837 : /*out*/ "=r" (_res) \
1838 : /*in*/ "r" (&_argvec[0]) \
1839 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1840 ); \
1841 lval = (__typeof__(lval)) _res; \
1842 } while (0)
1843
1844#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1845 do { \
1846 volatile OrigFn _orig = (orig); \
1847 volatile unsigned long _argvec[6]; \
1848 volatile unsigned long _res; \
1849 _argvec[0] = (unsigned long)_orig.nraddr; \
1850 _argvec[1] = (unsigned long)arg1; \
1851 _argvec[2] = (unsigned long)arg2; \
1852 _argvec[3] = (unsigned long)arg3; \
1853 _argvec[4] = (unsigned long)arg4; \
1854 _argvec[5] = (unsigned long)arg5; \
1855 __asm__ volatile( \
1856 "mr 11,%1\n\t" \
1857 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1858 "lwz 4,8(11)\n\t" \
1859 "lwz 5,12(11)\n\t" \
1860 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1861 "lwz 7,20(11)\n\t" \
1862 "lwz 11,0(11)\n\t" /* target->r11 */ \
1863 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1864 "mr %0,3" \
1865 : /*out*/ "=r" (_res) \
1866 : /*in*/ "r" (&_argvec[0]) \
1867 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1868 ); \
1869 lval = (__typeof__(lval)) _res; \
1870 } while (0)
1871
1872#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1873 do { \
1874 volatile OrigFn _orig = (orig); \
1875 volatile unsigned long _argvec[7]; \
1876 volatile unsigned long _res; \
1877 _argvec[0] = (unsigned long)_orig.nraddr; \
1878 _argvec[1] = (unsigned long)arg1; \
1879 _argvec[2] = (unsigned long)arg2; \
1880 _argvec[3] = (unsigned long)arg3; \
1881 _argvec[4] = (unsigned long)arg4; \
1882 _argvec[5] = (unsigned long)arg5; \
1883 _argvec[6] = (unsigned long)arg6; \
1884 __asm__ volatile( \
1885 "mr 11,%1\n\t" \
1886 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1887 "lwz 4,8(11)\n\t" \
1888 "lwz 5,12(11)\n\t" \
1889 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1890 "lwz 7,20(11)\n\t" \
1891 "lwz 8,24(11)\n\t" \
1892 "lwz 11,0(11)\n\t" /* target->r11 */ \
1893 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1894 "mr %0,3" \
1895 : /*out*/ "=r" (_res) \
1896 : /*in*/ "r" (&_argvec[0]) \
1897 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1898 ); \
1899 lval = (__typeof__(lval)) _res; \
1900 } while (0)
1901
1902#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1903 arg7) \
1904 do { \
1905 volatile OrigFn _orig = (orig); \
1906 volatile unsigned long _argvec[8]; \
1907 volatile unsigned long _res; \
1908 _argvec[0] = (unsigned long)_orig.nraddr; \
1909 _argvec[1] = (unsigned long)arg1; \
1910 _argvec[2] = (unsigned long)arg2; \
1911 _argvec[3] = (unsigned long)arg3; \
1912 _argvec[4] = (unsigned long)arg4; \
1913 _argvec[5] = (unsigned long)arg5; \
1914 _argvec[6] = (unsigned long)arg6; \
1915 _argvec[7] = (unsigned long)arg7; \
1916 __asm__ volatile( \
1917 "mr 11,%1\n\t" \
1918 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1919 "lwz 4,8(11)\n\t" \
1920 "lwz 5,12(11)\n\t" \
1921 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1922 "lwz 7,20(11)\n\t" \
1923 "lwz 8,24(11)\n\t" \
1924 "lwz 9,28(11)\n\t" \
1925 "lwz 11,0(11)\n\t" /* target->r11 */ \
1926 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1927 "mr %0,3" \
1928 : /*out*/ "=r" (_res) \
1929 : /*in*/ "r" (&_argvec[0]) \
1930 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1931 ); \
1932 lval = (__typeof__(lval)) _res; \
1933 } while (0)
1934
1935#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1936 arg7,arg8) \
1937 do { \
1938 volatile OrigFn _orig = (orig); \
1939 volatile unsigned long _argvec[9]; \
1940 volatile unsigned long _res; \
1941 _argvec[0] = (unsigned long)_orig.nraddr; \
1942 _argvec[1] = (unsigned long)arg1; \
1943 _argvec[2] = (unsigned long)arg2; \
1944 _argvec[3] = (unsigned long)arg3; \
1945 _argvec[4] = (unsigned long)arg4; \
1946 _argvec[5] = (unsigned long)arg5; \
1947 _argvec[6] = (unsigned long)arg6; \
1948 _argvec[7] = (unsigned long)arg7; \
1949 _argvec[8] = (unsigned long)arg8; \
1950 __asm__ volatile( \
1951 "mr 11,%1\n\t" \
1952 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1953 "lwz 4,8(11)\n\t" \
1954 "lwz 5,12(11)\n\t" \
1955 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1956 "lwz 7,20(11)\n\t" \
1957 "lwz 8,24(11)\n\t" \
1958 "lwz 9,28(11)\n\t" \
1959 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1960 "lwz 11,0(11)\n\t" /* target->r11 */ \
1961 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1962 "mr %0,3" \
1963 : /*out*/ "=r" (_res) \
1964 : /*in*/ "r" (&_argvec[0]) \
1965 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1966 ); \
1967 lval = (__typeof__(lval)) _res; \
1968 } while (0)
1969
1970#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1971 arg7,arg8,arg9) \
1972 do { \
1973 volatile OrigFn _orig = (orig); \
1974 volatile unsigned long _argvec[10]; \
1975 volatile unsigned long _res; \
1976 _argvec[0] = (unsigned long)_orig.nraddr; \
1977 _argvec[1] = (unsigned long)arg1; \
1978 _argvec[2] = (unsigned long)arg2; \
1979 _argvec[3] = (unsigned long)arg3; \
1980 _argvec[4] = (unsigned long)arg4; \
1981 _argvec[5] = (unsigned long)arg5; \
1982 _argvec[6] = (unsigned long)arg6; \
1983 _argvec[7] = (unsigned long)arg7; \
1984 _argvec[8] = (unsigned long)arg8; \
1985 _argvec[9] = (unsigned long)arg9; \
1986 __asm__ volatile( \
1987 "mr 11,%1\n\t" \
1988 "addi 1,1,-16\n\t" \
1989 /* arg9 */ \
1990 "lwz 3,36(11)\n\t" \
1991 "stw 3,8(1)\n\t" \
1992 /* args1-8 */ \
1993 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1994 "lwz 4,8(11)\n\t" \
1995 "lwz 5,12(11)\n\t" \
1996 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1997 "lwz 7,20(11)\n\t" \
1998 "lwz 8,24(11)\n\t" \
1999 "lwz 9,28(11)\n\t" \
2000 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2001 "lwz 11,0(11)\n\t" /* target->r11 */ \
2002 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2003 "addi 1,1,16\n\t" \
2004 "mr %0,3" \
2005 : /*out*/ "=r" (_res) \
2006 : /*in*/ "r" (&_argvec[0]) \
2007 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2008 ); \
2009 lval = (__typeof__(lval)) _res; \
2010 } while (0)
2011
2012#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2013 arg7,arg8,arg9,arg10) \
2014 do { \
2015 volatile OrigFn _orig = (orig); \
2016 volatile unsigned long _argvec[11]; \
2017 volatile unsigned long _res; \
2018 _argvec[0] = (unsigned long)_orig.nraddr; \
2019 _argvec[1] = (unsigned long)arg1; \
2020 _argvec[2] = (unsigned long)arg2; \
2021 _argvec[3] = (unsigned long)arg3; \
2022 _argvec[4] = (unsigned long)arg4; \
2023 _argvec[5] = (unsigned long)arg5; \
2024 _argvec[6] = (unsigned long)arg6; \
2025 _argvec[7] = (unsigned long)arg7; \
2026 _argvec[8] = (unsigned long)arg8; \
2027 _argvec[9] = (unsigned long)arg9; \
2028 _argvec[10] = (unsigned long)arg10; \
2029 __asm__ volatile( \
2030 "mr 11,%1\n\t" \
2031 "addi 1,1,-16\n\t" \
2032 /* arg10 */ \
2033 "lwz 3,40(11)\n\t" \
2034 "stw 3,12(1)\n\t" \
2035 /* arg9 */ \
2036 "lwz 3,36(11)\n\t" \
2037 "stw 3,8(1)\n\t" \
2038 /* args1-8 */ \
2039 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2040 "lwz 4,8(11)\n\t" \
2041 "lwz 5,12(11)\n\t" \
2042 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2043 "lwz 7,20(11)\n\t" \
2044 "lwz 8,24(11)\n\t" \
2045 "lwz 9,28(11)\n\t" \
2046 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2047 "lwz 11,0(11)\n\t" /* target->r11 */ \
2048 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2049 "addi 1,1,16\n\t" \
2050 "mr %0,3" \
2051 : /*out*/ "=r" (_res) \
2052 : /*in*/ "r" (&_argvec[0]) \
2053 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2054 ); \
2055 lval = (__typeof__(lval)) _res; \
2056 } while (0)
2057
2058#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2059 arg7,arg8,arg9,arg10,arg11) \
2060 do { \
2061 volatile OrigFn _orig = (orig); \
2062 volatile unsigned long _argvec[12]; \
2063 volatile unsigned long _res; \
2064 _argvec[0] = (unsigned long)_orig.nraddr; \
2065 _argvec[1] = (unsigned long)arg1; \
2066 _argvec[2] = (unsigned long)arg2; \
2067 _argvec[3] = (unsigned long)arg3; \
2068 _argvec[4] = (unsigned long)arg4; \
2069 _argvec[5] = (unsigned long)arg5; \
2070 _argvec[6] = (unsigned long)arg6; \
2071 _argvec[7] = (unsigned long)arg7; \
2072 _argvec[8] = (unsigned long)arg8; \
2073 _argvec[9] = (unsigned long)arg9; \
2074 _argvec[10] = (unsigned long)arg10; \
2075 _argvec[11] = (unsigned long)arg11; \
2076 __asm__ volatile( \
2077 "mr 11,%1\n\t" \
2078 "addi 1,1,-32\n\t" \
2079 /* arg11 */ \
2080 "lwz 3,44(11)\n\t" \
2081 "stw 3,16(1)\n\t" \
2082 /* arg10 */ \
2083 "lwz 3,40(11)\n\t" \
2084 "stw 3,12(1)\n\t" \
2085 /* arg9 */ \
2086 "lwz 3,36(11)\n\t" \
2087 "stw 3,8(1)\n\t" \
2088 /* args1-8 */ \
2089 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2090 "lwz 4,8(11)\n\t" \
2091 "lwz 5,12(11)\n\t" \
2092 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2093 "lwz 7,20(11)\n\t" \
2094 "lwz 8,24(11)\n\t" \
2095 "lwz 9,28(11)\n\t" \
2096 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2097 "lwz 11,0(11)\n\t" /* target->r11 */ \
2098 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2099 "addi 1,1,32\n\t" \
2100 "mr %0,3" \
2101 : /*out*/ "=r" (_res) \
2102 : /*in*/ "r" (&_argvec[0]) \
2103 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2104 ); \
2105 lval = (__typeof__(lval)) _res; \
2106 } while (0)
2107
2108#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2109 arg7,arg8,arg9,arg10,arg11,arg12) \
2110 do { \
2111 volatile OrigFn _orig = (orig); \
2112 volatile unsigned long _argvec[13]; \
2113 volatile unsigned long _res; \
2114 _argvec[0] = (unsigned long)_orig.nraddr; \
2115 _argvec[1] = (unsigned long)arg1; \
2116 _argvec[2] = (unsigned long)arg2; \
2117 _argvec[3] = (unsigned long)arg3; \
2118 _argvec[4] = (unsigned long)arg4; \
2119 _argvec[5] = (unsigned long)arg5; \
2120 _argvec[6] = (unsigned long)arg6; \
2121 _argvec[7] = (unsigned long)arg7; \
2122 _argvec[8] = (unsigned long)arg8; \
2123 _argvec[9] = (unsigned long)arg9; \
2124 _argvec[10] = (unsigned long)arg10; \
2125 _argvec[11] = (unsigned long)arg11; \
2126 _argvec[12] = (unsigned long)arg12; \
2127 __asm__ volatile( \
2128 "mr 11,%1\n\t" \
2129 "addi 1,1,-32\n\t" \
2130 /* arg12 */ \
2131 "lwz 3,48(11)\n\t" \
2132 "stw 3,20(1)\n\t" \
2133 /* arg11 */ \
2134 "lwz 3,44(11)\n\t" \
2135 "stw 3,16(1)\n\t" \
2136 /* arg10 */ \
2137 "lwz 3,40(11)\n\t" \
2138 "stw 3,12(1)\n\t" \
2139 /* arg9 */ \
2140 "lwz 3,36(11)\n\t" \
2141 "stw 3,8(1)\n\t" \
2142 /* args1-8 */ \
2143 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
2144 "lwz 4,8(11)\n\t" \
2145 "lwz 5,12(11)\n\t" \
2146 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
2147 "lwz 7,20(11)\n\t" \
2148 "lwz 8,24(11)\n\t" \
2149 "lwz 9,28(11)\n\t" \
2150 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2151 "lwz 11,0(11)\n\t" /* target->r11 */ \
2152 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2153 "addi 1,1,32\n\t" \
2154 "mr %0,3" \
2155 : /*out*/ "=r" (_res) \
2156 : /*in*/ "r" (&_argvec[0]) \
2157 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2158 ); \
2159 lval = (__typeof__(lval)) _res; \
2160 } while (0)
2161
sewardjf5c1a7f2006-10-17 01:32:48 +00002162#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +00002163
sewardjf5c1a7f2006-10-17 01:32:48 +00002164/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002165
sewardjf5c1a7f2006-10-17 01:32:48 +00002166#if defined(PLAT_ppc64_linux)
sewardj9734b202006-01-17 01:49:37 +00002167
2168/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2169
2170/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00002171#define __CALLER_SAVED_REGS \
2172 "lr", "ctr", "xer", \
2173 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2174 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2175 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00002176
2177/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2178 long) == 8. */
2179
sewardjd68ac3e2006-01-20 14:31:57 +00002180#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00002181 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002182 volatile OrigFn _orig = (orig); \
2183 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00002184 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002185 /* _argvec[0] holds current r2 across the call */ \
2186 _argvec[1] = (unsigned long)_orig.r2; \
2187 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00002188 __asm__ volatile( \
2189 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002190 "std 2,-16(11)\n\t" /* save tocptr */ \
2191 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2192 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002193 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2194 "mr 11,%1\n\t" \
2195 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002196 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002197 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002198 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002199 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2200 ); \
2201 lval = (__typeof__(lval)) _res; \
2202 } while (0)
2203
sewardjd68ac3e2006-01-20 14:31:57 +00002204#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00002205 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002206 volatile OrigFn _orig = (orig); \
2207 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00002208 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002209 /* _argvec[0] holds current r2 across the call */ \
2210 _argvec[1] = (unsigned long)_orig.r2; \
2211 _argvec[2] = (unsigned long)_orig.nraddr; \
2212 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00002213 __asm__ volatile( \
2214 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002215 "std 2,-16(11)\n\t" /* save tocptr */ \
2216 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2217 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2218 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002219 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2220 "mr 11,%1\n\t" \
2221 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002222 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002223 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002224 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002225 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2226 ); \
2227 lval = (__typeof__(lval)) _res; \
2228 } while (0)
2229
sewardjd68ac3e2006-01-20 14:31:57 +00002230#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00002231 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002232 volatile OrigFn _orig = (orig); \
2233 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00002234 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002235 /* _argvec[0] holds current r2 across the call */ \
2236 _argvec[1] = (unsigned long)_orig.r2; \
2237 _argvec[2] = (unsigned long)_orig.nraddr; \
2238 _argvec[2+1] = (unsigned long)arg1; \
2239 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00002240 __asm__ volatile( \
2241 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002242 "std 2,-16(11)\n\t" /* save tocptr */ \
2243 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2244 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00002245 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00002246 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002247 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2248 "mr 11,%1\n\t" \
2249 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002250 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002251 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002252 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002253 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2254 ); \
2255 lval = (__typeof__(lval)) _res; \
2256 } while (0)
2257
sewardjcd636392006-03-12 16:48:14 +00002258#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2259 do { \
2260 volatile OrigFn _orig = (orig); \
2261 volatile unsigned long _argvec[3+3]; \
2262 volatile unsigned long _res; \
2263 /* _argvec[0] holds current r2 across the call */ \
2264 _argvec[1] = (unsigned long)_orig.r2; \
2265 _argvec[2] = (unsigned long)_orig.nraddr; \
2266 _argvec[2+1] = (unsigned long)arg1; \
2267 _argvec[2+2] = (unsigned long)arg2; \
2268 _argvec[2+3] = (unsigned long)arg3; \
2269 __asm__ volatile( \
2270 "mr 11,%1\n\t" \
2271 "std 2,-16(11)\n\t" /* save tocptr */ \
2272 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2273 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2274 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2275 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2276 "ld 11, 0(11)\n\t" /* target->r11 */ \
2277 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2278 "mr 11,%1\n\t" \
2279 "mr %0,3\n\t" \
2280 "ld 2,-16(11)" /* restore tocptr */ \
2281 : /*out*/ "=r" (_res) \
2282 : /*in*/ "r" (&_argvec[2]) \
2283 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2284 ); \
2285 lval = (__typeof__(lval)) _res; \
2286 } while (0)
2287
2288#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2289 do { \
2290 volatile OrigFn _orig = (orig); \
2291 volatile unsigned long _argvec[3+4]; \
2292 volatile unsigned long _res; \
2293 /* _argvec[0] holds current r2 across the call */ \
2294 _argvec[1] = (unsigned long)_orig.r2; \
2295 _argvec[2] = (unsigned long)_orig.nraddr; \
2296 _argvec[2+1] = (unsigned long)arg1; \
2297 _argvec[2+2] = (unsigned long)arg2; \
2298 _argvec[2+3] = (unsigned long)arg3; \
2299 _argvec[2+4] = (unsigned long)arg4; \
2300 __asm__ volatile( \
2301 "mr 11,%1\n\t" \
2302 "std 2,-16(11)\n\t" /* save tocptr */ \
2303 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2304 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2305 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2306 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2307 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2308 "ld 11, 0(11)\n\t" /* target->r11 */ \
2309 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2310 "mr 11,%1\n\t" \
2311 "mr %0,3\n\t" \
2312 "ld 2,-16(11)" /* restore tocptr */ \
2313 : /*out*/ "=r" (_res) \
2314 : /*in*/ "r" (&_argvec[2]) \
2315 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2316 ); \
2317 lval = (__typeof__(lval)) _res; \
2318 } while (0)
2319
2320#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2321 do { \
2322 volatile OrigFn _orig = (orig); \
2323 volatile unsigned long _argvec[3+5]; \
2324 volatile unsigned long _res; \
2325 /* _argvec[0] holds current r2 across the call */ \
2326 _argvec[1] = (unsigned long)_orig.r2; \
2327 _argvec[2] = (unsigned long)_orig.nraddr; \
2328 _argvec[2+1] = (unsigned long)arg1; \
2329 _argvec[2+2] = (unsigned long)arg2; \
2330 _argvec[2+3] = (unsigned long)arg3; \
2331 _argvec[2+4] = (unsigned long)arg4; \
2332 _argvec[2+5] = (unsigned long)arg5; \
2333 __asm__ volatile( \
2334 "mr 11,%1\n\t" \
2335 "std 2,-16(11)\n\t" /* save tocptr */ \
2336 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2337 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2338 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2339 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2340 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2341 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2342 "ld 11, 0(11)\n\t" /* target->r11 */ \
2343 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2344 "mr 11,%1\n\t" \
2345 "mr %0,3\n\t" \
2346 "ld 2,-16(11)" /* restore tocptr */ \
2347 : /*out*/ "=r" (_res) \
2348 : /*in*/ "r" (&_argvec[2]) \
2349 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2350 ); \
2351 lval = (__typeof__(lval)) _res; \
2352 } while (0)
2353
2354#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2355 do { \
2356 volatile OrigFn _orig = (orig); \
2357 volatile unsigned long _argvec[3+6]; \
2358 volatile unsigned long _res; \
2359 /* _argvec[0] holds current r2 across the call */ \
2360 _argvec[1] = (unsigned long)_orig.r2; \
2361 _argvec[2] = (unsigned long)_orig.nraddr; \
2362 _argvec[2+1] = (unsigned long)arg1; \
2363 _argvec[2+2] = (unsigned long)arg2; \
2364 _argvec[2+3] = (unsigned long)arg3; \
2365 _argvec[2+4] = (unsigned long)arg4; \
2366 _argvec[2+5] = (unsigned long)arg5; \
2367 _argvec[2+6] = (unsigned long)arg6; \
2368 __asm__ volatile( \
2369 "mr 11,%1\n\t" \
2370 "std 2,-16(11)\n\t" /* save tocptr */ \
2371 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2372 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2373 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2374 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2375 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2376 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2377 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2378 "ld 11, 0(11)\n\t" /* target->r11 */ \
2379 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2380 "mr 11,%1\n\t" \
2381 "mr %0,3\n\t" \
2382 "ld 2,-16(11)" /* restore tocptr */ \
2383 : /*out*/ "=r" (_res) \
2384 : /*in*/ "r" (&_argvec[2]) \
2385 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2386 ); \
2387 lval = (__typeof__(lval)) _res; \
2388 } while (0)
2389
2390#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2391 arg7) \
2392 do { \
2393 volatile OrigFn _orig = (orig); \
2394 volatile unsigned long _argvec[3+7]; \
2395 volatile unsigned long _res; \
2396 /* _argvec[0] holds current r2 across the call */ \
2397 _argvec[1] = (unsigned long)_orig.r2; \
2398 _argvec[2] = (unsigned long)_orig.nraddr; \
2399 _argvec[2+1] = (unsigned long)arg1; \
2400 _argvec[2+2] = (unsigned long)arg2; \
2401 _argvec[2+3] = (unsigned long)arg3; \
2402 _argvec[2+4] = (unsigned long)arg4; \
2403 _argvec[2+5] = (unsigned long)arg5; \
2404 _argvec[2+6] = (unsigned long)arg6; \
2405 _argvec[2+7] = (unsigned long)arg7; \
2406 __asm__ volatile( \
2407 "mr 11,%1\n\t" \
2408 "std 2,-16(11)\n\t" /* save tocptr */ \
2409 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2410 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2411 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2412 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2413 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2414 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2415 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2416 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2417 "ld 11, 0(11)\n\t" /* target->r11 */ \
2418 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2419 "mr 11,%1\n\t" \
2420 "mr %0,3\n\t" \
2421 "ld 2,-16(11)" /* restore tocptr */ \
2422 : /*out*/ "=r" (_res) \
2423 : /*in*/ "r" (&_argvec[2]) \
2424 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2425 ); \
2426 lval = (__typeof__(lval)) _res; \
2427 } while (0)
2428
2429#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2430 arg7,arg8) \
2431 do { \
2432 volatile OrigFn _orig = (orig); \
2433 volatile unsigned long _argvec[3+8]; \
2434 volatile unsigned long _res; \
2435 /* _argvec[0] holds current r2 across the call */ \
2436 _argvec[1] = (unsigned long)_orig.r2; \
2437 _argvec[2] = (unsigned long)_orig.nraddr; \
2438 _argvec[2+1] = (unsigned long)arg1; \
2439 _argvec[2+2] = (unsigned long)arg2; \
2440 _argvec[2+3] = (unsigned long)arg3; \
2441 _argvec[2+4] = (unsigned long)arg4; \
2442 _argvec[2+5] = (unsigned long)arg5; \
2443 _argvec[2+6] = (unsigned long)arg6; \
2444 _argvec[2+7] = (unsigned long)arg7; \
2445 _argvec[2+8] = (unsigned long)arg8; \
2446 __asm__ volatile( \
2447 "mr 11,%1\n\t" \
2448 "std 2,-16(11)\n\t" /* save tocptr */ \
2449 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2450 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2451 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2452 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2453 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2454 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2455 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2456 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2457 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2458 "ld 11, 0(11)\n\t" /* target->r11 */ \
2459 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2460 "mr 11,%1\n\t" \
2461 "mr %0,3\n\t" \
2462 "ld 2,-16(11)" /* restore tocptr */ \
2463 : /*out*/ "=r" (_res) \
2464 : /*in*/ "r" (&_argvec[2]) \
2465 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2466 ); \
2467 lval = (__typeof__(lval)) _res; \
2468 } while (0)
2469
2470#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2471 arg7,arg8,arg9) \
2472 do { \
2473 volatile OrigFn _orig = (orig); \
2474 volatile unsigned long _argvec[3+9]; \
2475 volatile unsigned long _res; \
2476 /* _argvec[0] holds current r2 across the call */ \
2477 _argvec[1] = (unsigned long)_orig.r2; \
2478 _argvec[2] = (unsigned long)_orig.nraddr; \
2479 _argvec[2+1] = (unsigned long)arg1; \
2480 _argvec[2+2] = (unsigned long)arg2; \
2481 _argvec[2+3] = (unsigned long)arg3; \
2482 _argvec[2+4] = (unsigned long)arg4; \
2483 _argvec[2+5] = (unsigned long)arg5; \
2484 _argvec[2+6] = (unsigned long)arg6; \
2485 _argvec[2+7] = (unsigned long)arg7; \
2486 _argvec[2+8] = (unsigned long)arg8; \
2487 _argvec[2+9] = (unsigned long)arg9; \
2488 __asm__ volatile( \
2489 "mr 11,%1\n\t" \
2490 "std 2,-16(11)\n\t" /* save tocptr */ \
2491 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2492 "addi 1,1,-128\n\t" /* expand stack frame */ \
2493 /* arg9 */ \
2494 "ld 3,72(11)\n\t" \
2495 "std 3,112(1)\n\t" \
2496 /* args1-8 */ \
2497 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2498 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2499 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2500 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2501 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2502 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2503 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2504 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2505 "ld 11, 0(11)\n\t" /* target->r11 */ \
2506 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2507 "mr 11,%1\n\t" \
2508 "mr %0,3\n\t" \
2509 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2510 "addi 1,1,128" /* restore frame */ \
2511 : /*out*/ "=r" (_res) \
2512 : /*in*/ "r" (&_argvec[2]) \
2513 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2514 ); \
2515 lval = (__typeof__(lval)) _res; \
2516 } while (0)
2517
2518#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2519 arg7,arg8,arg9,arg10) \
2520 do { \
2521 volatile OrigFn _orig = (orig); \
2522 volatile unsigned long _argvec[3+10]; \
2523 volatile unsigned long _res; \
2524 /* _argvec[0] holds current r2 across the call */ \
2525 _argvec[1] = (unsigned long)_orig.r2; \
2526 _argvec[2] = (unsigned long)_orig.nraddr; \
2527 _argvec[2+1] = (unsigned long)arg1; \
2528 _argvec[2+2] = (unsigned long)arg2; \
2529 _argvec[2+3] = (unsigned long)arg3; \
2530 _argvec[2+4] = (unsigned long)arg4; \
2531 _argvec[2+5] = (unsigned long)arg5; \
2532 _argvec[2+6] = (unsigned long)arg6; \
2533 _argvec[2+7] = (unsigned long)arg7; \
2534 _argvec[2+8] = (unsigned long)arg8; \
2535 _argvec[2+9] = (unsigned long)arg9; \
2536 _argvec[2+10] = (unsigned long)arg10; \
2537 __asm__ volatile( \
2538 "mr 11,%1\n\t" \
2539 "std 2,-16(11)\n\t" /* save tocptr */ \
2540 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2541 "addi 1,1,-128\n\t" /* expand stack frame */ \
2542 /* arg10 */ \
2543 "ld 3,80(11)\n\t" \
2544 "std 3,120(1)\n\t" \
2545 /* arg9 */ \
2546 "ld 3,72(11)\n\t" \
2547 "std 3,112(1)\n\t" \
2548 /* args1-8 */ \
2549 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2550 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2551 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2552 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2553 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2554 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2555 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2556 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2557 "ld 11, 0(11)\n\t" /* target->r11 */ \
2558 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2559 "mr 11,%1\n\t" \
2560 "mr %0,3\n\t" \
2561 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2562 "addi 1,1,128" /* restore frame */ \
2563 : /*out*/ "=r" (_res) \
2564 : /*in*/ "r" (&_argvec[2]) \
2565 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2566 ); \
2567 lval = (__typeof__(lval)) _res; \
2568 } while (0)
2569
2570#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2571 arg7,arg8,arg9,arg10,arg11) \
2572 do { \
2573 volatile OrigFn _orig = (orig); \
2574 volatile unsigned long _argvec[3+11]; \
2575 volatile unsigned long _res; \
2576 /* _argvec[0] holds current r2 across the call */ \
2577 _argvec[1] = (unsigned long)_orig.r2; \
2578 _argvec[2] = (unsigned long)_orig.nraddr; \
2579 _argvec[2+1] = (unsigned long)arg1; \
2580 _argvec[2+2] = (unsigned long)arg2; \
2581 _argvec[2+3] = (unsigned long)arg3; \
2582 _argvec[2+4] = (unsigned long)arg4; \
2583 _argvec[2+5] = (unsigned long)arg5; \
2584 _argvec[2+6] = (unsigned long)arg6; \
2585 _argvec[2+7] = (unsigned long)arg7; \
2586 _argvec[2+8] = (unsigned long)arg8; \
2587 _argvec[2+9] = (unsigned long)arg9; \
2588 _argvec[2+10] = (unsigned long)arg10; \
2589 _argvec[2+11] = (unsigned long)arg11; \
2590 __asm__ volatile( \
2591 "mr 11,%1\n\t" \
2592 "std 2,-16(11)\n\t" /* save tocptr */ \
2593 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2594 "addi 1,1,-144\n\t" /* expand stack frame */ \
2595 /* arg11 */ \
2596 "ld 3,88(11)\n\t" \
2597 "std 3,128(1)\n\t" \
2598 /* arg10 */ \
2599 "ld 3,80(11)\n\t" \
2600 "std 3,120(1)\n\t" \
2601 /* arg9 */ \
2602 "ld 3,72(11)\n\t" \
2603 "std 3,112(1)\n\t" \
2604 /* args1-8 */ \
2605 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2606 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2607 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2608 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2609 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2610 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2611 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2612 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2613 "ld 11, 0(11)\n\t" /* target->r11 */ \
2614 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2615 "mr 11,%1\n\t" \
2616 "mr %0,3\n\t" \
2617 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2618 "addi 1,1,144" /* restore frame */ \
2619 : /*out*/ "=r" (_res) \
2620 : /*in*/ "r" (&_argvec[2]) \
2621 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2622 ); \
2623 lval = (__typeof__(lval)) _res; \
2624 } while (0)
2625
2626#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2627 arg7,arg8,arg9,arg10,arg11,arg12) \
2628 do { \
2629 volatile OrigFn _orig = (orig); \
2630 volatile unsigned long _argvec[3+12]; \
2631 volatile unsigned long _res; \
2632 /* _argvec[0] holds current r2 across the call */ \
2633 _argvec[1] = (unsigned long)_orig.r2; \
2634 _argvec[2] = (unsigned long)_orig.nraddr; \
2635 _argvec[2+1] = (unsigned long)arg1; \
2636 _argvec[2+2] = (unsigned long)arg2; \
2637 _argvec[2+3] = (unsigned long)arg3; \
2638 _argvec[2+4] = (unsigned long)arg4; \
2639 _argvec[2+5] = (unsigned long)arg5; \
2640 _argvec[2+6] = (unsigned long)arg6; \
2641 _argvec[2+7] = (unsigned long)arg7; \
2642 _argvec[2+8] = (unsigned long)arg8; \
2643 _argvec[2+9] = (unsigned long)arg9; \
2644 _argvec[2+10] = (unsigned long)arg10; \
2645 _argvec[2+11] = (unsigned long)arg11; \
2646 _argvec[2+12] = (unsigned long)arg12; \
2647 __asm__ volatile( \
2648 "mr 11,%1\n\t" \
2649 "std 2,-16(11)\n\t" /* save tocptr */ \
2650 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2651 "addi 1,1,-144\n\t" /* expand stack frame */ \
2652 /* arg12 */ \
2653 "ld 3,96(11)\n\t" \
2654 "std 3,136(1)\n\t" \
2655 /* arg11 */ \
2656 "ld 3,88(11)\n\t" \
2657 "std 3,128(1)\n\t" \
2658 /* arg10 */ \
2659 "ld 3,80(11)\n\t" \
2660 "std 3,120(1)\n\t" \
2661 /* arg9 */ \
2662 "ld 3,72(11)\n\t" \
2663 "std 3,112(1)\n\t" \
2664 /* args1-8 */ \
2665 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2666 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2667 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2668 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2669 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2670 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2671 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2672 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2673 "ld 11, 0(11)\n\t" /* target->r11 */ \
2674 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2675 "mr 11,%1\n\t" \
2676 "mr %0,3\n\t" \
2677 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2678 "addi 1,1,144" /* restore frame */ \
2679 : /*out*/ "=r" (_res) \
2680 : /*in*/ "r" (&_argvec[2]) \
2681 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2682 ); \
2683 lval = (__typeof__(lval)) _res; \
2684 } while (0)
2685
sewardjf5c1a7f2006-10-17 01:32:48 +00002686#endif /* PLAT_ppc64_linux */
2687
sewardj59570ff2010-01-01 11:59:33 +00002688/* ------------------------- arm-linux ------------------------- */
2689
2690#if defined(PLAT_arm_linux)
2691
2692/* These regs are trashed by the hidden call. */
2693#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
2694
2695/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
2696 long) == 4. */
2697
2698#define CALL_FN_W_v(lval, orig) \
2699 do { \
2700 volatile OrigFn _orig = (orig); \
2701 volatile unsigned long _argvec[1]; \
2702 volatile unsigned long _res; \
2703 _argvec[0] = (unsigned long)_orig.nraddr; \
2704 __asm__ volatile( \
2705 "ldr r4, [%1] \n\t" /* target->r4 */ \
2706 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2707 "mov %0, r0\n" \
2708 : /*out*/ "=r" (_res) \
2709 : /*in*/ "0" (&_argvec[0]) \
2710 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2711 ); \
2712 lval = (__typeof__(lval)) _res; \
2713 } while (0)
2714
2715#define CALL_FN_W_W(lval, orig, arg1) \
2716 do { \
2717 volatile OrigFn _orig = (orig); \
2718 volatile unsigned long _argvec[2]; \
2719 volatile unsigned long _res; \
2720 _argvec[0] = (unsigned long)_orig.nraddr; \
2721 _argvec[1] = (unsigned long)(arg1); \
2722 __asm__ volatile( \
2723 "ldr r0, [%1, #4] \n\t" \
2724 "ldr r4, [%1] \n\t" /* target->r4 */ \
2725 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2726 "mov %0, r0\n" \
2727 : /*out*/ "=r" (_res) \
2728 : /*in*/ "0" (&_argvec[0]) \
2729 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2730 ); \
2731 lval = (__typeof__(lval)) _res; \
2732 } while (0)
2733
2734#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2735 do { \
2736 volatile OrigFn _orig = (orig); \
2737 volatile unsigned long _argvec[3]; \
2738 volatile unsigned long _res; \
2739 _argvec[0] = (unsigned long)_orig.nraddr; \
2740 _argvec[1] = (unsigned long)(arg1); \
2741 _argvec[2] = (unsigned long)(arg2); \
2742 __asm__ volatile( \
2743 "ldr r0, [%1, #4] \n\t" \
2744 "ldr r1, [%1, #8] \n\t" \
2745 "ldr r4, [%1] \n\t" /* target->r4 */ \
2746 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2747 "mov %0, r0\n" \
2748 : /*out*/ "=r" (_res) \
2749 : /*in*/ "0" (&_argvec[0]) \
2750 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2751 ); \
2752 lval = (__typeof__(lval)) _res; \
2753 } while (0)
2754
2755#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2756 do { \
2757 volatile OrigFn _orig = (orig); \
2758 volatile unsigned long _argvec[4]; \
2759 volatile unsigned long _res; \
2760 _argvec[0] = (unsigned long)_orig.nraddr; \
2761 _argvec[1] = (unsigned long)(arg1); \
2762 _argvec[2] = (unsigned long)(arg2); \
2763 _argvec[3] = (unsigned long)(arg3); \
2764 __asm__ volatile( \
2765 "ldr r0, [%1, #4] \n\t" \
2766 "ldr r1, [%1, #8] \n\t" \
2767 "ldr r2, [%1, #12] \n\t" \
2768 "ldr r4, [%1] \n\t" /* target->r4 */ \
2769 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2770 "mov %0, r0\n" \
2771 : /*out*/ "=r" (_res) \
2772 : /*in*/ "0" (&_argvec[0]) \
2773 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2774 ); \
2775 lval = (__typeof__(lval)) _res; \
2776 } while (0)
2777
2778#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2779 do { \
2780 volatile OrigFn _orig = (orig); \
2781 volatile unsigned long _argvec[5]; \
2782 volatile unsigned long _res; \
2783 _argvec[0] = (unsigned long)_orig.nraddr; \
2784 _argvec[1] = (unsigned long)(arg1); \
2785 _argvec[2] = (unsigned long)(arg2); \
2786 _argvec[3] = (unsigned long)(arg3); \
2787 _argvec[4] = (unsigned long)(arg4); \
2788 __asm__ volatile( \
2789 "ldr r0, [%1, #4] \n\t" \
2790 "ldr r1, [%1, #8] \n\t" \
2791 "ldr r2, [%1, #12] \n\t" \
2792 "ldr r3, [%1, #16] \n\t" \
2793 "ldr r4, [%1] \n\t" /* target->r4 */ \
2794 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2795 "mov %0, r0" \
2796 : /*out*/ "=r" (_res) \
2797 : /*in*/ "0" (&_argvec[0]) \
2798 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2799 ); \
2800 lval = (__typeof__(lval)) _res; \
2801 } while (0)
2802
2803#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2804 do { \
2805 volatile OrigFn _orig = (orig); \
2806 volatile unsigned long _argvec[6]; \
2807 volatile unsigned long _res; \
2808 _argvec[0] = (unsigned long)_orig.nraddr; \
2809 _argvec[1] = (unsigned long)(arg1); \
2810 _argvec[2] = (unsigned long)(arg2); \
2811 _argvec[3] = (unsigned long)(arg3); \
2812 _argvec[4] = (unsigned long)(arg4); \
2813 _argvec[5] = (unsigned long)(arg5); \
2814 __asm__ volatile( \
2815 "ldr r0, [%1, #20] \n\t" \
2816 "push {r0} \n\t" \
2817 "ldr r0, [%1, #4] \n\t" \
2818 "ldr r1, [%1, #8] \n\t" \
2819 "ldr r2, [%1, #12] \n\t" \
2820 "ldr r3, [%1, #16] \n\t" \
2821 "ldr r4, [%1] \n\t" /* target->r4 */ \
2822 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2823 "add sp, sp, #4 \n\t" \
2824 "mov %0, r0" \
2825 : /*out*/ "=r" (_res) \
2826 : /*in*/ "0" (&_argvec[0]) \
2827 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2828 ); \
2829 lval = (__typeof__(lval)) _res; \
2830 } while (0)
2831
2832#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2833 do { \
2834 volatile OrigFn _orig = (orig); \
2835 volatile unsigned long _argvec[7]; \
2836 volatile unsigned long _res; \
2837 _argvec[0] = (unsigned long)_orig.nraddr; \
2838 _argvec[1] = (unsigned long)(arg1); \
2839 _argvec[2] = (unsigned long)(arg2); \
2840 _argvec[3] = (unsigned long)(arg3); \
2841 _argvec[4] = (unsigned long)(arg4); \
2842 _argvec[5] = (unsigned long)(arg5); \
2843 _argvec[6] = (unsigned long)(arg6); \
2844 __asm__ volatile( \
2845 "ldr r0, [%1, #20] \n\t" \
2846 "ldr r1, [%1, #24] \n\t" \
2847 "push {r0, r1} \n\t" \
2848 "ldr r0, [%1, #4] \n\t" \
2849 "ldr r1, [%1, #8] \n\t" \
2850 "ldr r2, [%1, #12] \n\t" \
2851 "ldr r3, [%1, #16] \n\t" \
2852 "ldr r4, [%1] \n\t" /* target->r4 */ \
2853 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2854 "add sp, sp, #8 \n\t" \
2855 "mov %0, r0" \
2856 : /*out*/ "=r" (_res) \
2857 : /*in*/ "0" (&_argvec[0]) \
2858 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2859 ); \
2860 lval = (__typeof__(lval)) _res; \
2861 } while (0)
2862
2863#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2864 arg7) \
2865 do { \
2866 volatile OrigFn _orig = (orig); \
2867 volatile unsigned long _argvec[8]; \
2868 volatile unsigned long _res; \
2869 _argvec[0] = (unsigned long)_orig.nraddr; \
2870 _argvec[1] = (unsigned long)(arg1); \
2871 _argvec[2] = (unsigned long)(arg2); \
2872 _argvec[3] = (unsigned long)(arg3); \
2873 _argvec[4] = (unsigned long)(arg4); \
2874 _argvec[5] = (unsigned long)(arg5); \
2875 _argvec[6] = (unsigned long)(arg6); \
2876 _argvec[7] = (unsigned long)(arg7); \
2877 __asm__ volatile( \
2878 "ldr r0, [%1, #20] \n\t" \
2879 "ldr r1, [%1, #24] \n\t" \
2880 "ldr r2, [%1, #28] \n\t" \
2881 "push {r0, r1, r2} \n\t" \
2882 "ldr r0, [%1, #4] \n\t" \
2883 "ldr r1, [%1, #8] \n\t" \
2884 "ldr r2, [%1, #12] \n\t" \
2885 "ldr r3, [%1, #16] \n\t" \
2886 "ldr r4, [%1] \n\t" /* target->r4 */ \
2887 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2888 "add sp, sp, #12 \n\t" \
2889 "mov %0, r0" \
2890 : /*out*/ "=r" (_res) \
2891 : /*in*/ "0" (&_argvec[0]) \
2892 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2893 ); \
2894 lval = (__typeof__(lval)) _res; \
2895 } while (0)
2896
2897#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2898 arg7,arg8) \
2899 do { \
2900 volatile OrigFn _orig = (orig); \
2901 volatile unsigned long _argvec[9]; \
2902 volatile unsigned long _res; \
2903 _argvec[0] = (unsigned long)_orig.nraddr; \
2904 _argvec[1] = (unsigned long)(arg1); \
2905 _argvec[2] = (unsigned long)(arg2); \
2906 _argvec[3] = (unsigned long)(arg3); \
2907 _argvec[4] = (unsigned long)(arg4); \
2908 _argvec[5] = (unsigned long)(arg5); \
2909 _argvec[6] = (unsigned long)(arg6); \
2910 _argvec[7] = (unsigned long)(arg7); \
2911 _argvec[8] = (unsigned long)(arg8); \
2912 __asm__ volatile( \
2913 "ldr r0, [%1, #20] \n\t" \
2914 "ldr r1, [%1, #24] \n\t" \
2915 "ldr r2, [%1, #28] \n\t" \
2916 "ldr r3, [%1, #32] \n\t" \
2917 "push {r0, r1, r2, r3} \n\t" \
2918 "ldr r0, [%1, #4] \n\t" \
2919 "ldr r1, [%1, #8] \n\t" \
2920 "ldr r2, [%1, #12] \n\t" \
2921 "ldr r3, [%1, #16] \n\t" \
2922 "ldr r4, [%1] \n\t" /* target->r4 */ \
2923 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2924 "add sp, sp, #16 \n\t" \
2925 "mov %0, r0" \
2926 : /*out*/ "=r" (_res) \
2927 : /*in*/ "0" (&_argvec[0]) \
2928 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2929 ); \
2930 lval = (__typeof__(lval)) _res; \
2931 } while (0)
2932
2933#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2934 arg7,arg8,arg9) \
2935 do { \
2936 volatile OrigFn _orig = (orig); \
2937 volatile unsigned long _argvec[10]; \
2938 volatile unsigned long _res; \
2939 _argvec[0] = (unsigned long)_orig.nraddr; \
2940 _argvec[1] = (unsigned long)(arg1); \
2941 _argvec[2] = (unsigned long)(arg2); \
2942 _argvec[3] = (unsigned long)(arg3); \
2943 _argvec[4] = (unsigned long)(arg4); \
2944 _argvec[5] = (unsigned long)(arg5); \
2945 _argvec[6] = (unsigned long)(arg6); \
2946 _argvec[7] = (unsigned long)(arg7); \
2947 _argvec[8] = (unsigned long)(arg8); \
2948 _argvec[9] = (unsigned long)(arg9); \
2949 __asm__ volatile( \
2950 "ldr r0, [%1, #20] \n\t" \
2951 "ldr r1, [%1, #24] \n\t" \
2952 "ldr r2, [%1, #28] \n\t" \
2953 "ldr r3, [%1, #32] \n\t" \
2954 "ldr r4, [%1, #36] \n\t" \
2955 "push {r0, r1, r2, r3, r4} \n\t" \
2956 "ldr r0, [%1, #4] \n\t" \
2957 "ldr r1, [%1, #8] \n\t" \
2958 "ldr r2, [%1, #12] \n\t" \
2959 "ldr r3, [%1, #16] \n\t" \
2960 "ldr r4, [%1] \n\t" /* target->r4 */ \
2961 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2962 "add sp, sp, #20 \n\t" \
2963 "mov %0, r0" \
2964 : /*out*/ "=r" (_res) \
2965 : /*in*/ "0" (&_argvec[0]) \
2966 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2967 ); \
2968 lval = (__typeof__(lval)) _res; \
2969 } while (0)
2970
2971#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2972 arg7,arg8,arg9,arg10) \
2973 do { \
2974 volatile OrigFn _orig = (orig); \
2975 volatile unsigned long _argvec[11]; \
2976 volatile unsigned long _res; \
2977 _argvec[0] = (unsigned long)_orig.nraddr; \
2978 _argvec[1] = (unsigned long)(arg1); \
2979 _argvec[2] = (unsigned long)(arg2); \
2980 _argvec[3] = (unsigned long)(arg3); \
2981 _argvec[4] = (unsigned long)(arg4); \
2982 _argvec[5] = (unsigned long)(arg5); \
2983 _argvec[6] = (unsigned long)(arg6); \
2984 _argvec[7] = (unsigned long)(arg7); \
2985 _argvec[8] = (unsigned long)(arg8); \
2986 _argvec[9] = (unsigned long)(arg9); \
2987 _argvec[10] = (unsigned long)(arg10); \
2988 __asm__ volatile( \
2989 "ldr r0, [%1, #40] \n\t" \
2990 "push {r0} \n\t" \
2991 "ldr r0, [%1, #20] \n\t" \
2992 "ldr r1, [%1, #24] \n\t" \
2993 "ldr r2, [%1, #28] \n\t" \
2994 "ldr r3, [%1, #32] \n\t" \
2995 "ldr r4, [%1, #36] \n\t" \
2996 "push {r0, r1, r2, r3, r4} \n\t" \
2997 "ldr r0, [%1, #4] \n\t" \
2998 "ldr r1, [%1, #8] \n\t" \
2999 "ldr r2, [%1, #12] \n\t" \
3000 "ldr r3, [%1, #16] \n\t" \
3001 "ldr r4, [%1] \n\t" /* target->r4 */ \
3002 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3003 "add sp, sp, #24 \n\t" \
3004 "mov %0, r0" \
3005 : /*out*/ "=r" (_res) \
3006 : /*in*/ "0" (&_argvec[0]) \
3007 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3008 ); \
3009 lval = (__typeof__(lval)) _res; \
3010 } while (0)
3011
3012#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3013 arg6,arg7,arg8,arg9,arg10, \
3014 arg11) \
3015 do { \
3016 volatile OrigFn _orig = (orig); \
3017 volatile unsigned long _argvec[12]; \
3018 volatile unsigned long _res; \
3019 _argvec[0] = (unsigned long)_orig.nraddr; \
3020 _argvec[1] = (unsigned long)(arg1); \
3021 _argvec[2] = (unsigned long)(arg2); \
3022 _argvec[3] = (unsigned long)(arg3); \
3023 _argvec[4] = (unsigned long)(arg4); \
3024 _argvec[5] = (unsigned long)(arg5); \
3025 _argvec[6] = (unsigned long)(arg6); \
3026 _argvec[7] = (unsigned long)(arg7); \
3027 _argvec[8] = (unsigned long)(arg8); \
3028 _argvec[9] = (unsigned long)(arg9); \
3029 _argvec[10] = (unsigned long)(arg10); \
3030 _argvec[11] = (unsigned long)(arg11); \
3031 __asm__ volatile( \
3032 "ldr r0, [%1, #40] \n\t" \
3033 "ldr r1, [%1, #44] \n\t" \
3034 "push {r0, r1} \n\t" \
3035 "ldr r0, [%1, #20] \n\t" \
3036 "ldr r1, [%1, #24] \n\t" \
3037 "ldr r2, [%1, #28] \n\t" \
3038 "ldr r3, [%1, #32] \n\t" \
3039 "ldr r4, [%1, #36] \n\t" \
3040 "push {r0, r1, r2, r3, r4} \n\t" \
3041 "ldr r0, [%1, #4] \n\t" \
3042 "ldr r1, [%1, #8] \n\t" \
3043 "ldr r2, [%1, #12] \n\t" \
3044 "ldr r3, [%1, #16] \n\t" \
3045 "ldr r4, [%1] \n\t" /* target->r4 */ \
3046 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3047 "add sp, sp, #28 \n\t" \
3048 "mov %0, r0" \
3049 : /*out*/ "=r" (_res) \
3050 : /*in*/ "0" (&_argvec[0]) \
3051 : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \
3052 ); \
3053 lval = (__typeof__(lval)) _res; \
3054 } while (0)
3055
3056#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
3057 arg6,arg7,arg8,arg9,arg10, \
3058 arg11,arg12) \
3059 do { \
3060 volatile OrigFn _orig = (orig); \
3061 volatile unsigned long _argvec[13]; \
3062 volatile unsigned long _res; \
3063 _argvec[0] = (unsigned long)_orig.nraddr; \
3064 _argvec[1] = (unsigned long)(arg1); \
3065 _argvec[2] = (unsigned long)(arg2); \
3066 _argvec[3] = (unsigned long)(arg3); \
3067 _argvec[4] = (unsigned long)(arg4); \
3068 _argvec[5] = (unsigned long)(arg5); \
3069 _argvec[6] = (unsigned long)(arg6); \
3070 _argvec[7] = (unsigned long)(arg7); \
3071 _argvec[8] = (unsigned long)(arg8); \
3072 _argvec[9] = (unsigned long)(arg9); \
3073 _argvec[10] = (unsigned long)(arg10); \
3074 _argvec[11] = (unsigned long)(arg11); \
3075 _argvec[12] = (unsigned long)(arg12); \
3076 __asm__ volatile( \
3077 "ldr r0, [%1, #40] \n\t" \
3078 "ldr r1, [%1, #44] \n\t" \
3079 "ldr r2, [%1, #48] \n\t" \
3080 "push {r0, r1, r2} \n\t" \
3081 "ldr r0, [%1, #20] \n\t" \
3082 "ldr r1, [%1, #24] \n\t" \
3083 "ldr r2, [%1, #28] \n\t" \
3084 "ldr r3, [%1, #32] \n\t" \
3085 "ldr r4, [%1, #36] \n\t" \
3086 "push {r0, r1, r2, r3, r4} \n\t" \
3087 "ldr r0, [%1, #4] \n\t" \
3088 "ldr r1, [%1, #8] \n\t" \
3089 "ldr r2, [%1, #12] \n\t" \
3090 "ldr r3, [%1, #16] \n\t" \
3091 "ldr r4, [%1] \n\t" /* target->r4 */ \
3092 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
3093 "add sp, sp, #32 \n\t" \
3094 "mov %0, r0" \
3095 : /*out*/ "=r" (_res) \
3096 : /*in*/ "0" (&_argvec[0]) \
3097 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3098 ); \
3099 lval = (__typeof__(lval)) _res; \
3100 } while (0)
3101
3102#endif /* PLAT_arm_linux */
3103
sewardjf5c1a7f2006-10-17 01:32:48 +00003104/* ------------------------ ppc32-aix5 ------------------------- */
3105
3106#if defined(PLAT_ppc32_aix5)
3107
3108/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3109
3110/* These regs are trashed by the hidden call. */
3111#define __CALLER_SAVED_REGS \
3112 "lr", "ctr", "xer", \
3113 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3114 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3115 "r11", "r12", "r13"
3116
3117/* Expand the stack frame, copying enough info that unwinding
3118 still works. Trashes r3. */
3119
3120#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3121 "addi 1,1,-" #_n_fr "\n\t" \
3122 "lwz 3," #_n_fr "(1)\n\t" \
3123 "stw 3,0(1)\n\t"
3124
3125#define VG_CONTRACT_FRAME_BY(_n_fr) \
3126 "addi 1,1," #_n_fr "\n\t"
3127
3128/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
3129 long) == 4. */
3130
3131#define CALL_FN_W_v(lval, orig) \
3132 do { \
3133 volatile OrigFn _orig = (orig); \
3134 volatile unsigned long _argvec[3+0]; \
3135 volatile unsigned long _res; \
3136 /* _argvec[0] holds current r2 across the call */ \
3137 _argvec[1] = (unsigned long)_orig.r2; \
3138 _argvec[2] = (unsigned long)_orig.nraddr; \
3139 __asm__ volatile( \
3140 "mr 11,%1\n\t" \
3141 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3142 "stw 2,-8(11)\n\t" /* save tocptr */ \
3143 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3144 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3145 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3146 "mr 11,%1\n\t" \
3147 "mr %0,3\n\t" \
3148 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3149 VG_CONTRACT_FRAME_BY(512) \
3150 : /*out*/ "=r" (_res) \
3151 : /*in*/ "r" (&_argvec[2]) \
3152 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3153 ); \
3154 lval = (__typeof__(lval)) _res; \
3155 } while (0)
3156
3157#define CALL_FN_W_W(lval, orig, arg1) \
3158 do { \
3159 volatile OrigFn _orig = (orig); \
3160 volatile unsigned long _argvec[3+1]; \
3161 volatile unsigned long _res; \
3162 /* _argvec[0] holds current r2 across the call */ \
3163 _argvec[1] = (unsigned long)_orig.r2; \
3164 _argvec[2] = (unsigned long)_orig.nraddr; \
3165 _argvec[2+1] = (unsigned long)arg1; \
3166 __asm__ volatile( \
3167 "mr 11,%1\n\t" \
3168 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3169 "stw 2,-8(11)\n\t" /* save tocptr */ \
3170 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3171 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3172 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3173 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3174 "mr 11,%1\n\t" \
3175 "mr %0,3\n\t" \
3176 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3177 VG_CONTRACT_FRAME_BY(512) \
3178 : /*out*/ "=r" (_res) \
3179 : /*in*/ "r" (&_argvec[2]) \
3180 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3181 ); \
3182 lval = (__typeof__(lval)) _res; \
3183 } while (0)
3184
3185#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3186 do { \
3187 volatile OrigFn _orig = (orig); \
3188 volatile unsigned long _argvec[3+2]; \
3189 volatile unsigned long _res; \
3190 /* _argvec[0] holds current r2 across the call */ \
3191 _argvec[1] = (unsigned long)_orig.r2; \
3192 _argvec[2] = (unsigned long)_orig.nraddr; \
3193 _argvec[2+1] = (unsigned long)arg1; \
3194 _argvec[2+2] = (unsigned long)arg2; \
3195 __asm__ volatile( \
3196 "mr 11,%1\n\t" \
3197 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3198 "stw 2,-8(11)\n\t" /* save tocptr */ \
3199 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3200 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3201 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3202 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3203 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3204 "mr 11,%1\n\t" \
3205 "mr %0,3\n\t" \
3206 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3207 VG_CONTRACT_FRAME_BY(512) \
3208 : /*out*/ "=r" (_res) \
3209 : /*in*/ "r" (&_argvec[2]) \
3210 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3211 ); \
3212 lval = (__typeof__(lval)) _res; \
3213 } while (0)
3214
3215#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3216 do { \
3217 volatile OrigFn _orig = (orig); \
3218 volatile unsigned long _argvec[3+3]; \
3219 volatile unsigned long _res; \
3220 /* _argvec[0] holds current r2 across the call */ \
3221 _argvec[1] = (unsigned long)_orig.r2; \
3222 _argvec[2] = (unsigned long)_orig.nraddr; \
3223 _argvec[2+1] = (unsigned long)arg1; \
3224 _argvec[2+2] = (unsigned long)arg2; \
3225 _argvec[2+3] = (unsigned long)arg3; \
3226 __asm__ volatile( \
3227 "mr 11,%1\n\t" \
3228 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3229 "stw 2,-8(11)\n\t" /* save tocptr */ \
3230 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3231 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3232 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3233 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3234 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3235 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3236 "mr 11,%1\n\t" \
3237 "mr %0,3\n\t" \
3238 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3239 VG_CONTRACT_FRAME_BY(512) \
3240 : /*out*/ "=r" (_res) \
3241 : /*in*/ "r" (&_argvec[2]) \
3242 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3243 ); \
3244 lval = (__typeof__(lval)) _res; \
3245 } while (0)
3246
3247#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3248 do { \
3249 volatile OrigFn _orig = (orig); \
3250 volatile unsigned long _argvec[3+4]; \
3251 volatile unsigned long _res; \
3252 /* _argvec[0] holds current r2 across the call */ \
3253 _argvec[1] = (unsigned long)_orig.r2; \
3254 _argvec[2] = (unsigned long)_orig.nraddr; \
3255 _argvec[2+1] = (unsigned long)arg1; \
3256 _argvec[2+2] = (unsigned long)arg2; \
3257 _argvec[2+3] = (unsigned long)arg3; \
3258 _argvec[2+4] = (unsigned long)arg4; \
3259 __asm__ volatile( \
3260 "mr 11,%1\n\t" \
3261 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3262 "stw 2,-8(11)\n\t" /* save tocptr */ \
3263 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3264 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3265 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3266 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3267 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3268 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3269 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3270 "mr 11,%1\n\t" \
3271 "mr %0,3\n\t" \
3272 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3273 VG_CONTRACT_FRAME_BY(512) \
3274 : /*out*/ "=r" (_res) \
3275 : /*in*/ "r" (&_argvec[2]) \
3276 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3277 ); \
3278 lval = (__typeof__(lval)) _res; \
3279 } while (0)
3280
3281#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3282 do { \
3283 volatile OrigFn _orig = (orig); \
3284 volatile unsigned long _argvec[3+5]; \
3285 volatile unsigned long _res; \
3286 /* _argvec[0] holds current r2 across the call */ \
3287 _argvec[1] = (unsigned long)_orig.r2; \
3288 _argvec[2] = (unsigned long)_orig.nraddr; \
3289 _argvec[2+1] = (unsigned long)arg1; \
3290 _argvec[2+2] = (unsigned long)arg2; \
3291 _argvec[2+3] = (unsigned long)arg3; \
3292 _argvec[2+4] = (unsigned long)arg4; \
3293 _argvec[2+5] = (unsigned long)arg5; \
3294 __asm__ volatile( \
3295 "mr 11,%1\n\t" \
3296 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3297 "stw 2,-8(11)\n\t" /* save tocptr */ \
3298 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3299 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3300 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3301 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3302 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3303 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3304 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3305 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3306 "mr 11,%1\n\t" \
3307 "mr %0,3\n\t" \
3308 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3309 VG_CONTRACT_FRAME_BY(512) \
3310 : /*out*/ "=r" (_res) \
3311 : /*in*/ "r" (&_argvec[2]) \
3312 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3313 ); \
3314 lval = (__typeof__(lval)) _res; \
3315 } while (0)
3316
3317#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3318 do { \
3319 volatile OrigFn _orig = (orig); \
3320 volatile unsigned long _argvec[3+6]; \
3321 volatile unsigned long _res; \
3322 /* _argvec[0] holds current r2 across the call */ \
3323 _argvec[1] = (unsigned long)_orig.r2; \
3324 _argvec[2] = (unsigned long)_orig.nraddr; \
3325 _argvec[2+1] = (unsigned long)arg1; \
3326 _argvec[2+2] = (unsigned long)arg2; \
3327 _argvec[2+3] = (unsigned long)arg3; \
3328 _argvec[2+4] = (unsigned long)arg4; \
3329 _argvec[2+5] = (unsigned long)arg5; \
3330 _argvec[2+6] = (unsigned long)arg6; \
3331 __asm__ volatile( \
3332 "mr 11,%1\n\t" \
3333 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3334 "stw 2,-8(11)\n\t" /* save tocptr */ \
3335 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3336 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3337 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3338 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3339 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3340 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3341 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3342 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3343 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3344 "mr 11,%1\n\t" \
3345 "mr %0,3\n\t" \
3346 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3347 VG_CONTRACT_FRAME_BY(512) \
3348 : /*out*/ "=r" (_res) \
3349 : /*in*/ "r" (&_argvec[2]) \
3350 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3351 ); \
3352 lval = (__typeof__(lval)) _res; \
3353 } while (0)
3354
3355#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3356 arg7) \
3357 do { \
3358 volatile OrigFn _orig = (orig); \
3359 volatile unsigned long _argvec[3+7]; \
3360 volatile unsigned long _res; \
3361 /* _argvec[0] holds current r2 across the call */ \
3362 _argvec[1] = (unsigned long)_orig.r2; \
3363 _argvec[2] = (unsigned long)_orig.nraddr; \
3364 _argvec[2+1] = (unsigned long)arg1; \
3365 _argvec[2+2] = (unsigned long)arg2; \
3366 _argvec[2+3] = (unsigned long)arg3; \
3367 _argvec[2+4] = (unsigned long)arg4; \
3368 _argvec[2+5] = (unsigned long)arg5; \
3369 _argvec[2+6] = (unsigned long)arg6; \
3370 _argvec[2+7] = (unsigned long)arg7; \
3371 __asm__ volatile( \
3372 "mr 11,%1\n\t" \
3373 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3374 "stw 2,-8(11)\n\t" /* save tocptr */ \
3375 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3376 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3377 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3378 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3379 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3380 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3381 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3382 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3383 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3384 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3385 "mr 11,%1\n\t" \
3386 "mr %0,3\n\t" \
3387 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3388 VG_CONTRACT_FRAME_BY(512) \
3389 : /*out*/ "=r" (_res) \
3390 : /*in*/ "r" (&_argvec[2]) \
3391 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3392 ); \
3393 lval = (__typeof__(lval)) _res; \
3394 } while (0)
3395
3396#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3397 arg7,arg8) \
3398 do { \
3399 volatile OrigFn _orig = (orig); \
3400 volatile unsigned long _argvec[3+8]; \
3401 volatile unsigned long _res; \
3402 /* _argvec[0] holds current r2 across the call */ \
3403 _argvec[1] = (unsigned long)_orig.r2; \
3404 _argvec[2] = (unsigned long)_orig.nraddr; \
3405 _argvec[2+1] = (unsigned long)arg1; \
3406 _argvec[2+2] = (unsigned long)arg2; \
3407 _argvec[2+3] = (unsigned long)arg3; \
3408 _argvec[2+4] = (unsigned long)arg4; \
3409 _argvec[2+5] = (unsigned long)arg5; \
3410 _argvec[2+6] = (unsigned long)arg6; \
3411 _argvec[2+7] = (unsigned long)arg7; \
3412 _argvec[2+8] = (unsigned long)arg8; \
3413 __asm__ volatile( \
3414 "mr 11,%1\n\t" \
3415 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3416 "stw 2,-8(11)\n\t" /* save tocptr */ \
3417 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3418 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3419 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3420 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3421 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3422 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3423 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3424 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3425 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3426 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3427 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3428 "mr 11,%1\n\t" \
3429 "mr %0,3\n\t" \
3430 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3431 VG_CONTRACT_FRAME_BY(512) \
3432 : /*out*/ "=r" (_res) \
3433 : /*in*/ "r" (&_argvec[2]) \
3434 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3435 ); \
3436 lval = (__typeof__(lval)) _res; \
3437 } while (0)
3438
3439#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3440 arg7,arg8,arg9) \
3441 do { \
3442 volatile OrigFn _orig = (orig); \
3443 volatile unsigned long _argvec[3+9]; \
3444 volatile unsigned long _res; \
3445 /* _argvec[0] holds current r2 across the call */ \
3446 _argvec[1] = (unsigned long)_orig.r2; \
3447 _argvec[2] = (unsigned long)_orig.nraddr; \
3448 _argvec[2+1] = (unsigned long)arg1; \
3449 _argvec[2+2] = (unsigned long)arg2; \
3450 _argvec[2+3] = (unsigned long)arg3; \
3451 _argvec[2+4] = (unsigned long)arg4; \
3452 _argvec[2+5] = (unsigned long)arg5; \
3453 _argvec[2+6] = (unsigned long)arg6; \
3454 _argvec[2+7] = (unsigned long)arg7; \
3455 _argvec[2+8] = (unsigned long)arg8; \
3456 _argvec[2+9] = (unsigned long)arg9; \
3457 __asm__ volatile( \
3458 "mr 11,%1\n\t" \
3459 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3460 "stw 2,-8(11)\n\t" /* save tocptr */ \
3461 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3462 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3463 /* arg9 */ \
3464 "lwz 3,36(11)\n\t" \
3465 "stw 3,56(1)\n\t" \
3466 /* args1-8 */ \
3467 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3468 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3469 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3470 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3471 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3472 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3473 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3474 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3475 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3476 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3477 "mr 11,%1\n\t" \
3478 "mr %0,3\n\t" \
3479 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3480 VG_CONTRACT_FRAME_BY(64) \
3481 VG_CONTRACT_FRAME_BY(512) \
3482 : /*out*/ "=r" (_res) \
3483 : /*in*/ "r" (&_argvec[2]) \
3484 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3485 ); \
3486 lval = (__typeof__(lval)) _res; \
3487 } while (0)
3488
3489#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3490 arg7,arg8,arg9,arg10) \
3491 do { \
3492 volatile OrigFn _orig = (orig); \
3493 volatile unsigned long _argvec[3+10]; \
3494 volatile unsigned long _res; \
3495 /* _argvec[0] holds current r2 across the call */ \
3496 _argvec[1] = (unsigned long)_orig.r2; \
3497 _argvec[2] = (unsigned long)_orig.nraddr; \
3498 _argvec[2+1] = (unsigned long)arg1; \
3499 _argvec[2+2] = (unsigned long)arg2; \
3500 _argvec[2+3] = (unsigned long)arg3; \
3501 _argvec[2+4] = (unsigned long)arg4; \
3502 _argvec[2+5] = (unsigned long)arg5; \
3503 _argvec[2+6] = (unsigned long)arg6; \
3504 _argvec[2+7] = (unsigned long)arg7; \
3505 _argvec[2+8] = (unsigned long)arg8; \
3506 _argvec[2+9] = (unsigned long)arg9; \
3507 _argvec[2+10] = (unsigned long)arg10; \
3508 __asm__ volatile( \
3509 "mr 11,%1\n\t" \
3510 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3511 "stw 2,-8(11)\n\t" /* save tocptr */ \
3512 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3513 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3514 /* arg10 */ \
3515 "lwz 3,40(11)\n\t" \
3516 "stw 3,60(1)\n\t" \
3517 /* arg9 */ \
3518 "lwz 3,36(11)\n\t" \
3519 "stw 3,56(1)\n\t" \
3520 /* args1-8 */ \
3521 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3522 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3523 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3524 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3525 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3526 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3527 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3528 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3529 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3530 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3531 "mr 11,%1\n\t" \
3532 "mr %0,3\n\t" \
3533 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3534 VG_CONTRACT_FRAME_BY(64) \
3535 VG_CONTRACT_FRAME_BY(512) \
3536 : /*out*/ "=r" (_res) \
3537 : /*in*/ "r" (&_argvec[2]) \
3538 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3539 ); \
3540 lval = (__typeof__(lval)) _res; \
3541 } while (0)
3542
3543#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3544 arg7,arg8,arg9,arg10,arg11) \
3545 do { \
3546 volatile OrigFn _orig = (orig); \
3547 volatile unsigned long _argvec[3+11]; \
3548 volatile unsigned long _res; \
3549 /* _argvec[0] holds current r2 across the call */ \
3550 _argvec[1] = (unsigned long)_orig.r2; \
3551 _argvec[2] = (unsigned long)_orig.nraddr; \
3552 _argvec[2+1] = (unsigned long)arg1; \
3553 _argvec[2+2] = (unsigned long)arg2; \
3554 _argvec[2+3] = (unsigned long)arg3; \
3555 _argvec[2+4] = (unsigned long)arg4; \
3556 _argvec[2+5] = (unsigned long)arg5; \
3557 _argvec[2+6] = (unsigned long)arg6; \
3558 _argvec[2+7] = (unsigned long)arg7; \
3559 _argvec[2+8] = (unsigned long)arg8; \
3560 _argvec[2+9] = (unsigned long)arg9; \
3561 _argvec[2+10] = (unsigned long)arg10; \
3562 _argvec[2+11] = (unsigned long)arg11; \
3563 __asm__ volatile( \
3564 "mr 11,%1\n\t" \
3565 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3566 "stw 2,-8(11)\n\t" /* save tocptr */ \
3567 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3568 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3569 /* arg11 */ \
3570 "lwz 3,44(11)\n\t" \
3571 "stw 3,64(1)\n\t" \
3572 /* arg10 */ \
3573 "lwz 3,40(11)\n\t" \
3574 "stw 3,60(1)\n\t" \
3575 /* arg9 */ \
3576 "lwz 3,36(11)\n\t" \
3577 "stw 3,56(1)\n\t" \
3578 /* args1-8 */ \
3579 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3580 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3581 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3582 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3583 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3584 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3585 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3586 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3587 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3588 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3589 "mr 11,%1\n\t" \
3590 "mr %0,3\n\t" \
3591 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3592 VG_CONTRACT_FRAME_BY(72) \
3593 VG_CONTRACT_FRAME_BY(512) \
3594 : /*out*/ "=r" (_res) \
3595 : /*in*/ "r" (&_argvec[2]) \
3596 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3597 ); \
3598 lval = (__typeof__(lval)) _res; \
3599 } while (0)
3600
3601#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3602 arg7,arg8,arg9,arg10,arg11,arg12) \
3603 do { \
3604 volatile OrigFn _orig = (orig); \
3605 volatile unsigned long _argvec[3+12]; \
3606 volatile unsigned long _res; \
3607 /* _argvec[0] holds current r2 across the call */ \
3608 _argvec[1] = (unsigned long)_orig.r2; \
3609 _argvec[2] = (unsigned long)_orig.nraddr; \
3610 _argvec[2+1] = (unsigned long)arg1; \
3611 _argvec[2+2] = (unsigned long)arg2; \
3612 _argvec[2+3] = (unsigned long)arg3; \
3613 _argvec[2+4] = (unsigned long)arg4; \
3614 _argvec[2+5] = (unsigned long)arg5; \
3615 _argvec[2+6] = (unsigned long)arg6; \
3616 _argvec[2+7] = (unsigned long)arg7; \
3617 _argvec[2+8] = (unsigned long)arg8; \
3618 _argvec[2+9] = (unsigned long)arg9; \
3619 _argvec[2+10] = (unsigned long)arg10; \
3620 _argvec[2+11] = (unsigned long)arg11; \
3621 _argvec[2+12] = (unsigned long)arg12; \
3622 __asm__ volatile( \
3623 "mr 11,%1\n\t" \
3624 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3625 "stw 2,-8(11)\n\t" /* save tocptr */ \
3626 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3627 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3628 /* arg12 */ \
3629 "lwz 3,48(11)\n\t" \
3630 "stw 3,68(1)\n\t" \
3631 /* arg11 */ \
3632 "lwz 3,44(11)\n\t" \
3633 "stw 3,64(1)\n\t" \
3634 /* arg10 */ \
3635 "lwz 3,40(11)\n\t" \
3636 "stw 3,60(1)\n\t" \
3637 /* arg9 */ \
3638 "lwz 3,36(11)\n\t" \
3639 "stw 3,56(1)\n\t" \
3640 /* args1-8 */ \
3641 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3642 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3643 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3644 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3645 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3646 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3647 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3648 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3649 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3650 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3651 "mr 11,%1\n\t" \
3652 "mr %0,3\n\t" \
3653 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3654 VG_CONTRACT_FRAME_BY(72) \
3655 VG_CONTRACT_FRAME_BY(512) \
3656 : /*out*/ "=r" (_res) \
3657 : /*in*/ "r" (&_argvec[2]) \
3658 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3659 ); \
3660 lval = (__typeof__(lval)) _res; \
3661 } while (0)
3662
3663#endif /* PLAT_ppc32_aix5 */
3664
3665/* ------------------------ ppc64-aix5 ------------------------- */
3666
3667#if defined(PLAT_ppc64_aix5)
3668
3669/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3670
3671/* These regs are trashed by the hidden call. */
3672#define __CALLER_SAVED_REGS \
3673 "lr", "ctr", "xer", \
3674 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3675 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3676 "r11", "r12", "r13"
3677
3678/* Expand the stack frame, copying enough info that unwinding
3679 still works. Trashes r3. */
3680
3681#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3682 "addi 1,1,-" #_n_fr "\n\t" \
3683 "ld 3," #_n_fr "(1)\n\t" \
3684 "std 3,0(1)\n\t"
3685
3686#define VG_CONTRACT_FRAME_BY(_n_fr) \
3687 "addi 1,1," #_n_fr "\n\t"
3688
3689/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
3690 long) == 8. */
3691
3692#define CALL_FN_W_v(lval, orig) \
3693 do { \
3694 volatile OrigFn _orig = (orig); \
3695 volatile unsigned long _argvec[3+0]; \
3696 volatile unsigned long _res; \
3697 /* _argvec[0] holds current r2 across the call */ \
3698 _argvec[1] = (unsigned long)_orig.r2; \
3699 _argvec[2] = (unsigned long)_orig.nraddr; \
3700 __asm__ volatile( \
3701 "mr 11,%1\n\t" \
3702 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3703 "std 2,-16(11)\n\t" /* save tocptr */ \
3704 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3705 "ld 11, 0(11)\n\t" /* target->r11 */ \
3706 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3707 "mr 11,%1\n\t" \
3708 "mr %0,3\n\t" \
3709 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3710 VG_CONTRACT_FRAME_BY(512) \
3711 : /*out*/ "=r" (_res) \
3712 : /*in*/ "r" (&_argvec[2]) \
3713 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3714 ); \
3715 lval = (__typeof__(lval)) _res; \
3716 } while (0)
3717
3718#define CALL_FN_W_W(lval, orig, arg1) \
3719 do { \
3720 volatile OrigFn _orig = (orig); \
3721 volatile unsigned long _argvec[3+1]; \
3722 volatile unsigned long _res; \
3723 /* _argvec[0] holds current r2 across the call */ \
3724 _argvec[1] = (unsigned long)_orig.r2; \
3725 _argvec[2] = (unsigned long)_orig.nraddr; \
3726 _argvec[2+1] = (unsigned long)arg1; \
3727 __asm__ volatile( \
3728 "mr 11,%1\n\t" \
3729 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3730 "std 2,-16(11)\n\t" /* save tocptr */ \
3731 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3732 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3733 "ld 11, 0(11)\n\t" /* target->r11 */ \
3734 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3735 "mr 11,%1\n\t" \
3736 "mr %0,3\n\t" \
3737 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3738 VG_CONTRACT_FRAME_BY(512) \
3739 : /*out*/ "=r" (_res) \
3740 : /*in*/ "r" (&_argvec[2]) \
3741 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3742 ); \
3743 lval = (__typeof__(lval)) _res; \
3744 } while (0)
3745
3746#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3747 do { \
3748 volatile OrigFn _orig = (orig); \
3749 volatile unsigned long _argvec[3+2]; \
3750 volatile unsigned long _res; \
3751 /* _argvec[0] holds current r2 across the call */ \
3752 _argvec[1] = (unsigned long)_orig.r2; \
3753 _argvec[2] = (unsigned long)_orig.nraddr; \
3754 _argvec[2+1] = (unsigned long)arg1; \
3755 _argvec[2+2] = (unsigned long)arg2; \
3756 __asm__ volatile( \
3757 "mr 11,%1\n\t" \
3758 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3759 "std 2,-16(11)\n\t" /* save tocptr */ \
3760 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3761 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3762 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3763 "ld 11, 0(11)\n\t" /* target->r11 */ \
3764 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3765 "mr 11,%1\n\t" \
3766 "mr %0,3\n\t" \
3767 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3768 VG_CONTRACT_FRAME_BY(512) \
3769 : /*out*/ "=r" (_res) \
3770 : /*in*/ "r" (&_argvec[2]) \
3771 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3772 ); \
3773 lval = (__typeof__(lval)) _res; \
3774 } while (0)
3775
3776#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3777 do { \
3778 volatile OrigFn _orig = (orig); \
3779 volatile unsigned long _argvec[3+3]; \
3780 volatile unsigned long _res; \
3781 /* _argvec[0] holds current r2 across the call */ \
3782 _argvec[1] = (unsigned long)_orig.r2; \
3783 _argvec[2] = (unsigned long)_orig.nraddr; \
3784 _argvec[2+1] = (unsigned long)arg1; \
3785 _argvec[2+2] = (unsigned long)arg2; \
3786 _argvec[2+3] = (unsigned long)arg3; \
3787 __asm__ volatile( \
3788 "mr 11,%1\n\t" \
3789 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3790 "std 2,-16(11)\n\t" /* save tocptr */ \
3791 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3792 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3793 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3794 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3795 "ld 11, 0(11)\n\t" /* target->r11 */ \
3796 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3797 "mr 11,%1\n\t" \
3798 "mr %0,3\n\t" \
3799 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3800 VG_CONTRACT_FRAME_BY(512) \
3801 : /*out*/ "=r" (_res) \
3802 : /*in*/ "r" (&_argvec[2]) \
3803 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3804 ); \
3805 lval = (__typeof__(lval)) _res; \
3806 } while (0)
3807
3808#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3809 do { \
3810 volatile OrigFn _orig = (orig); \
3811 volatile unsigned long _argvec[3+4]; \
3812 volatile unsigned long _res; \
3813 /* _argvec[0] holds current r2 across the call */ \
3814 _argvec[1] = (unsigned long)_orig.r2; \
3815 _argvec[2] = (unsigned long)_orig.nraddr; \
3816 _argvec[2+1] = (unsigned long)arg1; \
3817 _argvec[2+2] = (unsigned long)arg2; \
3818 _argvec[2+3] = (unsigned long)arg3; \
3819 _argvec[2+4] = (unsigned long)arg4; \
3820 __asm__ volatile( \
3821 "mr 11,%1\n\t" \
3822 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3823 "std 2,-16(11)\n\t" /* save tocptr */ \
3824 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3825 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3826 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3827 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3828 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3829 "ld 11, 0(11)\n\t" /* target->r11 */ \
3830 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3831 "mr 11,%1\n\t" \
3832 "mr %0,3\n\t" \
3833 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3834 VG_CONTRACT_FRAME_BY(512) \
3835 : /*out*/ "=r" (_res) \
3836 : /*in*/ "r" (&_argvec[2]) \
3837 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3838 ); \
3839 lval = (__typeof__(lval)) _res; \
3840 } while (0)
3841
3842#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3843 do { \
3844 volatile OrigFn _orig = (orig); \
3845 volatile unsigned long _argvec[3+5]; \
3846 volatile unsigned long _res; \
3847 /* _argvec[0] holds current r2 across the call */ \
3848 _argvec[1] = (unsigned long)_orig.r2; \
3849 _argvec[2] = (unsigned long)_orig.nraddr; \
3850 _argvec[2+1] = (unsigned long)arg1; \
3851 _argvec[2+2] = (unsigned long)arg2; \
3852 _argvec[2+3] = (unsigned long)arg3; \
3853 _argvec[2+4] = (unsigned long)arg4; \
3854 _argvec[2+5] = (unsigned long)arg5; \
3855 __asm__ volatile( \
3856 "mr 11,%1\n\t" \
3857 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3858 "std 2,-16(11)\n\t" /* save tocptr */ \
3859 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3860 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3861 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3862 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3863 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3864 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3865 "ld 11, 0(11)\n\t" /* target->r11 */ \
3866 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3867 "mr 11,%1\n\t" \
3868 "mr %0,3\n\t" \
3869 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3870 VG_CONTRACT_FRAME_BY(512) \
3871 : /*out*/ "=r" (_res) \
3872 : /*in*/ "r" (&_argvec[2]) \
3873 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3874 ); \
3875 lval = (__typeof__(lval)) _res; \
3876 } while (0)
3877
3878#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3879 do { \
3880 volatile OrigFn _orig = (orig); \
3881 volatile unsigned long _argvec[3+6]; \
3882 volatile unsigned long _res; \
3883 /* _argvec[0] holds current r2 across the call */ \
3884 _argvec[1] = (unsigned long)_orig.r2; \
3885 _argvec[2] = (unsigned long)_orig.nraddr; \
3886 _argvec[2+1] = (unsigned long)arg1; \
3887 _argvec[2+2] = (unsigned long)arg2; \
3888 _argvec[2+3] = (unsigned long)arg3; \
3889 _argvec[2+4] = (unsigned long)arg4; \
3890 _argvec[2+5] = (unsigned long)arg5; \
3891 _argvec[2+6] = (unsigned long)arg6; \
3892 __asm__ volatile( \
3893 "mr 11,%1\n\t" \
3894 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3895 "std 2,-16(11)\n\t" /* save tocptr */ \
3896 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3897 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3898 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3899 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3900 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3901 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3902 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3903 "ld 11, 0(11)\n\t" /* target->r11 */ \
3904 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3905 "mr 11,%1\n\t" \
3906 "mr %0,3\n\t" \
3907 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3908 VG_CONTRACT_FRAME_BY(512) \
3909 : /*out*/ "=r" (_res) \
3910 : /*in*/ "r" (&_argvec[2]) \
3911 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3912 ); \
3913 lval = (__typeof__(lval)) _res; \
3914 } while (0)
3915
3916#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3917 arg7) \
3918 do { \
3919 volatile OrigFn _orig = (orig); \
3920 volatile unsigned long _argvec[3+7]; \
3921 volatile unsigned long _res; \
3922 /* _argvec[0] holds current r2 across the call */ \
3923 _argvec[1] = (unsigned long)_orig.r2; \
3924 _argvec[2] = (unsigned long)_orig.nraddr; \
3925 _argvec[2+1] = (unsigned long)arg1; \
3926 _argvec[2+2] = (unsigned long)arg2; \
3927 _argvec[2+3] = (unsigned long)arg3; \
3928 _argvec[2+4] = (unsigned long)arg4; \
3929 _argvec[2+5] = (unsigned long)arg5; \
3930 _argvec[2+6] = (unsigned long)arg6; \
3931 _argvec[2+7] = (unsigned long)arg7; \
3932 __asm__ volatile( \
3933 "mr 11,%1\n\t" \
3934 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3935 "std 2,-16(11)\n\t" /* save tocptr */ \
3936 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3937 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3938 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3939 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3940 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3941 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3942 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3943 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3944 "ld 11, 0(11)\n\t" /* target->r11 */ \
3945 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3946 "mr 11,%1\n\t" \
3947 "mr %0,3\n\t" \
3948 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3949 VG_CONTRACT_FRAME_BY(512) \
3950 : /*out*/ "=r" (_res) \
3951 : /*in*/ "r" (&_argvec[2]) \
3952 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3953 ); \
3954 lval = (__typeof__(lval)) _res; \
3955 } while (0)
3956
3957#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3958 arg7,arg8) \
3959 do { \
3960 volatile OrigFn _orig = (orig); \
3961 volatile unsigned long _argvec[3+8]; \
3962 volatile unsigned long _res; \
3963 /* _argvec[0] holds current r2 across the call */ \
3964 _argvec[1] = (unsigned long)_orig.r2; \
3965 _argvec[2] = (unsigned long)_orig.nraddr; \
3966 _argvec[2+1] = (unsigned long)arg1; \
3967 _argvec[2+2] = (unsigned long)arg2; \
3968 _argvec[2+3] = (unsigned long)arg3; \
3969 _argvec[2+4] = (unsigned long)arg4; \
3970 _argvec[2+5] = (unsigned long)arg5; \
3971 _argvec[2+6] = (unsigned long)arg6; \
3972 _argvec[2+7] = (unsigned long)arg7; \
3973 _argvec[2+8] = (unsigned long)arg8; \
3974 __asm__ volatile( \
3975 "mr 11,%1\n\t" \
3976 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3977 "std 2,-16(11)\n\t" /* save tocptr */ \
3978 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3979 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3980 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3981 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3982 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3983 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3984 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3985 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3986 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3987 "ld 11, 0(11)\n\t" /* target->r11 */ \
3988 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3989 "mr 11,%1\n\t" \
3990 "mr %0,3\n\t" \
3991 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3992 VG_CONTRACT_FRAME_BY(512) \
3993 : /*out*/ "=r" (_res) \
3994 : /*in*/ "r" (&_argvec[2]) \
3995 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3996 ); \
3997 lval = (__typeof__(lval)) _res; \
3998 } while (0)
3999
4000#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4001 arg7,arg8,arg9) \
4002 do { \
4003 volatile OrigFn _orig = (orig); \
4004 volatile unsigned long _argvec[3+9]; \
4005 volatile unsigned long _res; \
4006 /* _argvec[0] holds current r2 across the call */ \
4007 _argvec[1] = (unsigned long)_orig.r2; \
4008 _argvec[2] = (unsigned long)_orig.nraddr; \
4009 _argvec[2+1] = (unsigned long)arg1; \
4010 _argvec[2+2] = (unsigned long)arg2; \
4011 _argvec[2+3] = (unsigned long)arg3; \
4012 _argvec[2+4] = (unsigned long)arg4; \
4013 _argvec[2+5] = (unsigned long)arg5; \
4014 _argvec[2+6] = (unsigned long)arg6; \
4015 _argvec[2+7] = (unsigned long)arg7; \
4016 _argvec[2+8] = (unsigned long)arg8; \
4017 _argvec[2+9] = (unsigned long)arg9; \
4018 __asm__ volatile( \
4019 "mr 11,%1\n\t" \
4020 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4021 "std 2,-16(11)\n\t" /* save tocptr */ \
4022 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4023 VG_EXPAND_FRAME_BY_trashes_r3(128) \
4024 /* arg9 */ \
4025 "ld 3,72(11)\n\t" \
4026 "std 3,112(1)\n\t" \
4027 /* args1-8 */ \
4028 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4029 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4030 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4031 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4032 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4033 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4034 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4035 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4036 "ld 11, 0(11)\n\t" /* target->r11 */ \
4037 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4038 "mr 11,%1\n\t" \
4039 "mr %0,3\n\t" \
4040 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4041 VG_CONTRACT_FRAME_BY(128) \
4042 VG_CONTRACT_FRAME_BY(512) \
4043 : /*out*/ "=r" (_res) \
4044 : /*in*/ "r" (&_argvec[2]) \
4045 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4046 ); \
4047 lval = (__typeof__(lval)) _res; \
4048 } while (0)
4049
4050#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4051 arg7,arg8,arg9,arg10) \
4052 do { \
4053 volatile OrigFn _orig = (orig); \
4054 volatile unsigned long _argvec[3+10]; \
4055 volatile unsigned long _res; \
4056 /* _argvec[0] holds current r2 across the call */ \
4057 _argvec[1] = (unsigned long)_orig.r2; \
4058 _argvec[2] = (unsigned long)_orig.nraddr; \
4059 _argvec[2+1] = (unsigned long)arg1; \
4060 _argvec[2+2] = (unsigned long)arg2; \
4061 _argvec[2+3] = (unsigned long)arg3; \
4062 _argvec[2+4] = (unsigned long)arg4; \
4063 _argvec[2+5] = (unsigned long)arg5; \
4064 _argvec[2+6] = (unsigned long)arg6; \
4065 _argvec[2+7] = (unsigned long)arg7; \
4066 _argvec[2+8] = (unsigned long)arg8; \
4067 _argvec[2+9] = (unsigned long)arg9; \
4068 _argvec[2+10] = (unsigned long)arg10; \
4069 __asm__ volatile( \
4070 "mr 11,%1\n\t" \
4071 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4072 "std 2,-16(11)\n\t" /* save tocptr */ \
4073 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4074 VG_EXPAND_FRAME_BY_trashes_r3(128) \
4075 /* arg10 */ \
4076 "ld 3,80(11)\n\t" \
4077 "std 3,120(1)\n\t" \
4078 /* arg9 */ \
4079 "ld 3,72(11)\n\t" \
4080 "std 3,112(1)\n\t" \
4081 /* args1-8 */ \
4082 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4083 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4084 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4085 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4086 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4087 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4088 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4089 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4090 "ld 11, 0(11)\n\t" /* target->r11 */ \
4091 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4092 "mr 11,%1\n\t" \
4093 "mr %0,3\n\t" \
4094 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4095 VG_CONTRACT_FRAME_BY(128) \
4096 VG_CONTRACT_FRAME_BY(512) \
4097 : /*out*/ "=r" (_res) \
4098 : /*in*/ "r" (&_argvec[2]) \
4099 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4100 ); \
4101 lval = (__typeof__(lval)) _res; \
4102 } while (0)
4103
4104#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4105 arg7,arg8,arg9,arg10,arg11) \
4106 do { \
4107 volatile OrigFn _orig = (orig); \
4108 volatile unsigned long _argvec[3+11]; \
4109 volatile unsigned long _res; \
4110 /* _argvec[0] holds current r2 across the call */ \
4111 _argvec[1] = (unsigned long)_orig.r2; \
4112 _argvec[2] = (unsigned long)_orig.nraddr; \
4113 _argvec[2+1] = (unsigned long)arg1; \
4114 _argvec[2+2] = (unsigned long)arg2; \
4115 _argvec[2+3] = (unsigned long)arg3; \
4116 _argvec[2+4] = (unsigned long)arg4; \
4117 _argvec[2+5] = (unsigned long)arg5; \
4118 _argvec[2+6] = (unsigned long)arg6; \
4119 _argvec[2+7] = (unsigned long)arg7; \
4120 _argvec[2+8] = (unsigned long)arg8; \
4121 _argvec[2+9] = (unsigned long)arg9; \
4122 _argvec[2+10] = (unsigned long)arg10; \
4123 _argvec[2+11] = (unsigned long)arg11; \
4124 __asm__ volatile( \
4125 "mr 11,%1\n\t" \
4126 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4127 "std 2,-16(11)\n\t" /* save tocptr */ \
4128 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4129 VG_EXPAND_FRAME_BY_trashes_r3(144) \
4130 /* arg11 */ \
4131 "ld 3,88(11)\n\t" \
4132 "std 3,128(1)\n\t" \
4133 /* arg10 */ \
4134 "ld 3,80(11)\n\t" \
4135 "std 3,120(1)\n\t" \
4136 /* arg9 */ \
4137 "ld 3,72(11)\n\t" \
4138 "std 3,112(1)\n\t" \
4139 /* args1-8 */ \
4140 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4141 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4142 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4143 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4144 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4145 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4146 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4147 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4148 "ld 11, 0(11)\n\t" /* target->r11 */ \
4149 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4150 "mr 11,%1\n\t" \
4151 "mr %0,3\n\t" \
4152 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4153 VG_CONTRACT_FRAME_BY(144) \
4154 VG_CONTRACT_FRAME_BY(512) \
4155 : /*out*/ "=r" (_res) \
4156 : /*in*/ "r" (&_argvec[2]) \
4157 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4158 ); \
4159 lval = (__typeof__(lval)) _res; \
4160 } while (0)
4161
4162#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4163 arg7,arg8,arg9,arg10,arg11,arg12) \
4164 do { \
4165 volatile OrigFn _orig = (orig); \
4166 volatile unsigned long _argvec[3+12]; \
4167 volatile unsigned long _res; \
4168 /* _argvec[0] holds current r2 across the call */ \
4169 _argvec[1] = (unsigned long)_orig.r2; \
4170 _argvec[2] = (unsigned long)_orig.nraddr; \
4171 _argvec[2+1] = (unsigned long)arg1; \
4172 _argvec[2+2] = (unsigned long)arg2; \
4173 _argvec[2+3] = (unsigned long)arg3; \
4174 _argvec[2+4] = (unsigned long)arg4; \
4175 _argvec[2+5] = (unsigned long)arg5; \
4176 _argvec[2+6] = (unsigned long)arg6; \
4177 _argvec[2+7] = (unsigned long)arg7; \
4178 _argvec[2+8] = (unsigned long)arg8; \
4179 _argvec[2+9] = (unsigned long)arg9; \
4180 _argvec[2+10] = (unsigned long)arg10; \
4181 _argvec[2+11] = (unsigned long)arg11; \
4182 _argvec[2+12] = (unsigned long)arg12; \
4183 __asm__ volatile( \
4184 "mr 11,%1\n\t" \
4185 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4186 "std 2,-16(11)\n\t" /* save tocptr */ \
4187 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4188 VG_EXPAND_FRAME_BY_trashes_r3(144) \
4189 /* arg12 */ \
4190 "ld 3,96(11)\n\t" \
4191 "std 3,136(1)\n\t" \
4192 /* arg11 */ \
4193 "ld 3,88(11)\n\t" \
4194 "std 3,128(1)\n\t" \
4195 /* arg10 */ \
4196 "ld 3,80(11)\n\t" \
4197 "std 3,120(1)\n\t" \
4198 /* arg9 */ \
4199 "ld 3,72(11)\n\t" \
4200 "std 3,112(1)\n\t" \
4201 /* args1-8 */ \
4202 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4203 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4204 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4205 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4206 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4207 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4208 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4209 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4210 "ld 11, 0(11)\n\t" /* target->r11 */ \
4211 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4212 "mr 11,%1\n\t" \
4213 "mr %0,3\n\t" \
4214 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4215 VG_CONTRACT_FRAME_BY(144) \
4216 VG_CONTRACT_FRAME_BY(512) \
4217 : /*out*/ "=r" (_res) \
4218 : /*in*/ "r" (&_argvec[2]) \
4219 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4220 ); \
4221 lval = (__typeof__(lval)) _res; \
4222 } while (0)
4223
4224#endif /* PLAT_ppc64_aix5 */
sewardj9734b202006-01-17 01:49:37 +00004225
sewardj0ec07f32006-01-12 12:32:32 +00004226
4227/* ------------------------------------------------------------------ */
4228/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
4229/* */
njn30d76c62005-06-18 15:07:39 +00004230/* ------------------------------------------------------------------ */
4231
sewardj2e93c502002-04-12 11:12:52 +00004232/* Some request codes. There are many more of these, but most are not
4233 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00004234 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00004235
sewardj0ec07f32006-01-12 12:32:32 +00004236 Core ones are in the range 0x00000000--0x0000ffff. The non-public
4237 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00004238*/
4239
sewardj0ec07f32006-01-12 12:32:32 +00004240/* These macros are used by tools -- they must be public, but don't
4241 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00004242#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00004243 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00004244#define VG_IS_TOOL_USERREQ(a, b, v) \
4245 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00004246
sewardj5ce4b152006-03-11 12:57:41 +00004247/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
4248 This enum comprises an ABI exported by Valgrind to programs
4249 which use client requests. DO NOT CHANGE THE ORDER OF THESE
4250 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00004251typedef
njn4c791212003-05-02 17:53:54 +00004252 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
4253 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00004254
sewardj0ec07f32006-01-12 12:32:32 +00004255 /* These allow any function to be called from the simulated
4256 CPU but run on the real CPU. Nb: the first arg passed to
4257 the function is always the ThreadId of the running
4258 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00004259 function, etc. */
njn4c791212003-05-02 17:53:54 +00004260 VG_USERREQ__CLIENT_CALL0 = 0x1101,
4261 VG_USERREQ__CLIENT_CALL1 = 0x1102,
4262 VG_USERREQ__CLIENT_CALL2 = 0x1103,
4263 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00004264
sewardj0ec07f32006-01-12 12:32:32 +00004265 /* Can be useful in regression testing suites -- eg. can
4266 send Valgrind's output to /dev/null and still count
4267 errors. */
njn4c791212003-05-02 17:53:54 +00004268 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00004269
sewardj0ec07f32006-01-12 12:32:32 +00004270 /* These are useful and can be interpreted by any tool that
4271 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00004272 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
4273 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00004274 /* Memory pool support. */
4275 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
4276 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
4277 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
4278 VG_USERREQ__MEMPOOL_FREE = 0x1306,
sewardj2c1c9df2006-07-28 00:06:37 +00004279 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
sewardjc740d762006-10-05 17:59:23 +00004280 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
4281 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
4282 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
njnd7994182003-10-02 13:44:04 +00004283
fitzhardinge39de4b42003-10-31 07:12:21 +00004284 /* Allow printfs to valgrind log. */
sewardjc560fb32010-01-28 15:23:54 +00004285 /* The first two pass the va_list argument by value, which
4286 assumes it is the same size as or smaller than a UWord,
4287 which generally isn't the case. Hence are deprecated.
4288 The second two pass the vargs by reference and so are
4289 immune to this problem. */
4290 /* both :: char* fmt, va_list vargs (DEPRECATED) */
njn30d76c62005-06-18 15:07:39 +00004291 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00004292 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
sewardjc560fb32010-01-28 15:23:54 +00004293 /* both :: char* fmt, va_list* vargs */
4294 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
4295 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
rjwalsh0140af52005-06-04 20:42:33 +00004296
4297 /* Stack support. */
4298 VG_USERREQ__STACK_REGISTER = 0x1501,
4299 VG_USERREQ__STACK_DEREGISTER = 0x1502,
sewardjc8259b82009-04-22 22:42:10 +00004300 VG_USERREQ__STACK_CHANGE = 0x1503,
4301
4302 /* Wine support */
sewardj5c659622010-08-20 18:22:07 +00004303 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
4304
4305 /* Querying of debug info. */
4306 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701
njn25e49d8e72002-09-23 09:36:25 +00004307 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00004308
sewardj0ec07f32006-01-12 12:32:32 +00004309#if !defined(__GNUC__)
4310# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00004311#endif
sewardj2e93c502002-04-12 11:12:52 +00004312
bartfa5115a2010-09-02 09:33:02 +00004313
4314/*
4315 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
4316 * client request and whose value equals the client request result.
4317 */
4318
4319#if defined(NVALGRIND)
4320
4321#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
4322 _zzq_default, _zzq_request, \
4323 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4324 (_zzq_default)
4325
4326#else /*defined(NVALGRIND)*/
4327
4328#if defined(_MSC_VER)
4329
4330#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
4331 _zzq_default, _zzq_request, \
4332 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4333 (vg_VALGRIND_DO_CLIENT_REQUEST_EXPR((uintptr_t)(_zzq_default), \
4334 (_zzq_request), (uintptr_t)(_zzq_arg1), (uintptr_t)(_zzq_arg2), \
4335 (uintptr_t)(_zzq_arg3), (uintptr_t)(_zzq_arg4), \
4336 (uintptr_t)(_zzq_arg5)))
4337
4338static __inline unsigned
4339vg_VALGRIND_DO_CLIENT_REQUEST_EXPR(uintptr_t _zzq_default,
4340 unsigned _zzq_request, uintptr_t _zzq_arg1,
4341 uintptr_t _zzq_arg2, uintptr_t _zzq_arg3,
4342 uintptr_t _zzq_arg4, uintptr_t _zzq_arg5)
4343{
4344 unsigned _zzq_rlval;
4345 VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request,
4346 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5);
4347 return _zzq_rlval;
4348}
4349
4350#else /*defined(_MSC_VER)*/
4351
4352#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
4353 _zzq_default, _zzq_request, \
4354 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4355 (__extension__({unsigned int _zzq_rlval; \
4356 VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request, \
4357 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
4358 _zzq_rlval; \
4359 }))
4360
4361#endif /*defined(_MSC_VER)*/
4362
4363#endif /*defined(NVALGRIND)*/
4364
4365
sewardj0ec07f32006-01-12 12:32:32 +00004366/* Returns the number of Valgrinds this code is running under. That
4367 is, 0 if running natively, 1 if running under Valgrind, 2 if
4368 running under Valgrind which is running under another Valgrind,
4369 etc. */
bartfa5115a2010-09-02 09:33:02 +00004370#define RUNNING_ON_VALGRIND \
4371 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \
4372 VG_USERREQ__RUNNING_ON_VALGRIND, \
4373 0, 0, 0, 0, 0) \
sewardjde4a1d02002-03-22 01:27:54 +00004374
4375
sewardj18d75132002-05-16 11:06:21 +00004376/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
4377 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
4378 since it provides a way to make sure valgrind will retranslate the
4379 invalidated area. Returns no value. */
sewardj0ec07f32006-01-12 12:32:32 +00004380#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
4381 {unsigned int _qzz_res; \
4382 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4383 VG_USERREQ__DISCARD_TRANSLATIONS, \
sewardj9af10a12006-02-01 14:59:42 +00004384 _qzz_addr, _qzz_len, 0, 0, 0); \
sewardj18d75132002-05-16 11:06:21 +00004385 }
4386
njn26aba4d2005-05-16 13:31:23 +00004387
sewardj0ec07f32006-01-12 12:32:32 +00004388/* These requests are for getting Valgrind itself to print something.
njnd55f0d92009-08-03 01:38:56 +00004389 Possibly with a backtrace. This is a really ugly hack. The return value
4390 is the number of characters printed, excluding the "**<pid>** " part at the
4391 start and the backtrace (if present). */
sewardj0ec07f32006-01-12 12:32:32 +00004392
4393#if defined(NVALGRIND)
4394
4395# define VALGRIND_PRINTF(...)
4396# define VALGRIND_PRINTF_BACKTRACE(...)
njn26aba4d2005-05-16 13:31:23 +00004397
4398#else /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00004399
bart7f489812010-08-27 10:05:27 +00004400#if !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00004401/* Modern GCC will optimize the static routine out if unused,
4402 and unused attribute will shut down warnings about it. */
4403static int VALGRIND_PRINTF(const char *format, ...)
4404 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00004405#endif
sewardj7eca0cc2006-04-12 17:15:35 +00004406static int
bart0da2c772010-09-01 10:18:36 +00004407#if defined(_MSC_VER)
4408__inline
4409#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00004410VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00004411{
njnc6168192004-11-29 13:54:10 +00004412 unsigned long _qzz_res;
sewardjc560fb32010-01-28 15:23:54 +00004413 va_list vargs;
4414 va_start(vargs, format);
bart0da2c772010-09-01 10:18:36 +00004415#if defined(_MSC_VER)
4416 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4417 VG_USERREQ__PRINTF_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00004418 (uintptr_t)format,
4419 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00004420 0, 0, 0);
4421#else
sewardjc560fb32010-01-28 15:23:54 +00004422 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4423 VG_USERREQ__PRINTF_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00004424 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00004425 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00004426 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00004427#endif
sewardjc560fb32010-01-28 15:23:54 +00004428 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00004429 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00004430}
4431
bart7f489812010-08-27 10:05:27 +00004432#if !defined(_MSC_VER)
sewardj7eca0cc2006-04-12 17:15:35 +00004433static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
4434 __attribute__((format(__printf__, 1, 2), __unused__));
bart7f489812010-08-27 10:05:27 +00004435#endif
sewardj7eca0cc2006-04-12 17:15:35 +00004436static int
bart0da2c772010-09-01 10:18:36 +00004437#if defined(_MSC_VER)
4438__inline
4439#endif
fitzhardingea09a1b52003-11-07 23:09:48 +00004440VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00004441{
njnc6168192004-11-29 13:54:10 +00004442 unsigned long _qzz_res;
sewardjc560fb32010-01-28 15:23:54 +00004443 va_list vargs;
4444 va_start(vargs, format);
bart0da2c772010-09-01 10:18:36 +00004445#if defined(_MSC_VER)
4446 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4447 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
bartfa5115a2010-09-02 09:33:02 +00004448 (uintptr_t)format,
4449 (uintptr_t)&vargs,
bart0da2c772010-09-01 10:18:36 +00004450 0, 0, 0);
4451#else
sewardjc560fb32010-01-28 15:23:54 +00004452 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4453 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00004454 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00004455 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00004456 0, 0, 0);
bart0da2c772010-09-01 10:18:36 +00004457#endif
sewardjc560fb32010-01-28 15:23:54 +00004458 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00004459 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00004460}
4461
fitzhardinge39de4b42003-10-31 07:12:21 +00004462#endif /* NVALGRIND */
sewardj18d75132002-05-16 11:06:21 +00004463
sewardj0ec07f32006-01-12 12:32:32 +00004464
njn3e884182003-04-15 13:03:23 +00004465/* These requests allow control to move from the simulated CPU to the
njn1319b492006-11-20 22:02:40 +00004466 real CPU, calling an arbitary function.
4467
4468 Note that the current ThreadId is inserted as the first argument.
4469 So this call:
4470
4471 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
4472
4473 requires f to have this signature:
4474
4475 Word f(Word tid, Word arg1, Word arg2)
4476
4477 where "Word" is a word-sized type.
njn45fb4d32007-12-05 21:51:50 +00004478
4479 Note that these client requests are not entirely reliable. For example,
4480 if you call a function with them that subsequently calls printf(),
4481 there's a high chance Valgrind will crash. Generally, your prospects of
4482 these working are made higher if the called function does not refer to
4483 any global variables, and does not refer to any libc or other functions
4484 (printf et al). Any kind of entanglement with libc or dynamic linking is
4485 likely to have a bad outcome, for tricky reasons which we've grappled
4486 with a lot in the past.
njn1319b492006-11-20 22:02:40 +00004487*/
sewardj0ec07f32006-01-12 12:32:32 +00004488#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
sewardj315dc8d2006-08-28 21:13:06 +00004489 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004490 ({unsigned long _qyy_res; \
4491 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4492 VG_USERREQ__CLIENT_CALL0, \
4493 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004494 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004495 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004496 })
4497
sewardj0ec07f32006-01-12 12:32:32 +00004498#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
sewardj315dc8d2006-08-28 21:13:06 +00004499 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004500 ({unsigned long _qyy_res; \
4501 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4502 VG_USERREQ__CLIENT_CALL1, \
4503 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004504 _qyy_arg1, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004505 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004506 })
4507
sewardj0ec07f32006-01-12 12:32:32 +00004508#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
sewardj315dc8d2006-08-28 21:13:06 +00004509 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004510 ({unsigned long _qyy_res; \
4511 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4512 VG_USERREQ__CLIENT_CALL2, \
4513 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004514 _qyy_arg1, _qyy_arg2, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004515 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004516 })
4517
sewardj0ec07f32006-01-12 12:32:32 +00004518#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
sewardj315dc8d2006-08-28 21:13:06 +00004519 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004520 ({unsigned long _qyy_res; \
4521 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4522 VG_USERREQ__CLIENT_CALL3, \
4523 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004524 _qyy_arg1, _qyy_arg2, \
4525 _qyy_arg3, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004526 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004527 })
4528
4529
nethercote7cc9c232004-01-21 15:08:04 +00004530/* Counts the number of errors that have been recorded by a tool. Nb:
4531 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00004532 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00004533#define VALGRIND_COUNT_ERRORS \
sewardj315dc8d2006-08-28 21:13:06 +00004534 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004535 ({unsigned int _qyy_res; \
4536 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4537 VG_USERREQ__COUNT_ERRORS, \
sewardj9af10a12006-02-01 14:59:42 +00004538 0, 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004539 _qyy_res; \
njn47363ab2003-04-21 13:24:40 +00004540 })
4541
njn3ac96952009-07-09 23:35:44 +00004542/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
4543 when heap blocks are allocated in order to give accurate results. This
4544 happens automatically for the standard allocator functions such as
4545 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
4546 delete[], etc.
njnd7994182003-10-02 13:44:04 +00004547
njn3ac96952009-07-09 23:35:44 +00004548 But if your program uses a custom allocator, this doesn't automatically
4549 happen, and Valgrind will not do as well. For example, if you allocate
4550 superblocks with mmap() and then allocates chunks of the superblocks, all
4551 Valgrind's observations will be at the mmap() level and it won't know that
4552 the chunks should be considered separate entities. In Memcheck's case,
4553 that means you probably won't get heap block overrun detection (because
4554 there won't be redzones marked as unaddressable) and you definitely won't
4555 get any leak detection.
4556
4557 The following client requests allow a custom allocator to be annotated so
4558 that it can be handled accurately by Valgrind.
4559
4560 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
4561 by a malloc()-like function. For Memcheck (an illustrative case), this
4562 does two things:
4563
4564 - It records that the block has been allocated. This means any addresses
4565 within the block mentioned in error messages will be
4566 identified as belonging to the block. It also means that if the block
4567 isn't freed it will be detected by the leak checker.
4568
4569 - It marks the block as being addressable and undefined (if 'is_zeroed' is
4570 not set), or addressable and defined (if 'is_zeroed' is set). This
4571 controls how accesses to the block by the program are handled.
4572
4573 'addr' is the start of the usable block (ie. after any
4574 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
4575 can apply redzones -- these are blocks of padding at the start and end of
4576 each block. Adding redzones is recommended as it makes it much more likely
4577 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
4578 zeroed (or filled with another predictable value), as is the case for
4579 calloc().
4580
4581 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
4582 heap block -- that will be used by the client program -- is allocated.
4583 It's best to put it at the outermost level of the allocator if possible;
4584 for example, if you have a function my_alloc() which calls
4585 internal_alloc(), and the client request is put inside internal_alloc(),
4586 stack traces relating to the heap block will contain entries for both
4587 my_alloc() and internal_alloc(), which is probably not what you want.
4588
njnb965efb2009-08-10 07:36:54 +00004589 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
4590 custom blocks from within a heap block, B, that has been allocated with
4591 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
4592 -- the custom blocks will take precedence.
4593
njn3ac96952009-07-09 23:35:44 +00004594 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
4595 Memcheck, it does two things:
4596
4597 - It records that the block has been deallocated. This assumes that the
4598 block was annotated as having been allocated via
4599 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
4600
4601 - It marks the block as being unaddressable.
4602
4603 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
4604 heap block is deallocated.
4605
4606 In many cases, these two client requests will not be enough to get your
4607 allocator working well with Memcheck. More specifically, if your allocator
4608 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
4609 will be necessary to mark the memory as addressable just before the zeroing
4610 occurs, otherwise you'll get a lot of invalid write errors. For example,
4611 you'll need to do this if your allocator recycles freed blocks, but it
4612 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
4613 Alternatively, if your allocator reuses freed blocks for allocator-internal
4614 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
4615
4616 Really, what's happening is a blurring of the lines between the client
4617 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
4618 memory should be considered unaddressable to the client program, but the
4619 allocator knows more than the rest of the client program and so may be able
4620 to safely access it. Extra client requests are necessary for Valgrind to
4621 understand the distinction between the allocator and the rest of the
4622 program.
4623
4624 Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it
4625 has to be emulated with MALLOCLIKE/FREELIKE and memory copying.
4626
njn32f8d8c2009-07-15 02:31:45 +00004627 Ignored if addr == 0.
njn3ac96952009-07-09 23:35:44 +00004628*/
sewardj0ec07f32006-01-12 12:32:32 +00004629#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
4630 {unsigned int _qzz_res; \
4631 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4632 VG_USERREQ__MALLOCLIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00004633 addr, sizeB, rzB, is_zeroed, 0); \
njnd7994182003-10-02 13:44:04 +00004634 }
4635
njn32f8d8c2009-07-15 02:31:45 +00004636/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
4637 Ignored if addr == 0.
4638*/
sewardj0ec07f32006-01-12 12:32:32 +00004639#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
4640 {unsigned int _qzz_res; \
4641 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4642 VG_USERREQ__FREELIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00004643 addr, rzB, 0, 0, 0); \
njnd7994182003-10-02 13:44:04 +00004644 }
4645
rjwalshbc0bb832004-06-19 18:12:36 +00004646/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004647#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
4648 {unsigned int _qzz_res; \
4649 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4650 VG_USERREQ__CREATE_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00004651 pool, rzB, is_zeroed, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004652 }
4653
4654/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004655#define VALGRIND_DESTROY_MEMPOOL(pool) \
4656 {unsigned int _qzz_res; \
4657 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4658 VG_USERREQ__DESTROY_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00004659 pool, 0, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004660 }
4661
4662/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004663#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
4664 {unsigned int _qzz_res; \
4665 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4666 VG_USERREQ__MEMPOOL_ALLOC, \
sewardj9af10a12006-02-01 14:59:42 +00004667 pool, addr, size, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004668 }
4669
4670/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004671#define VALGRIND_MEMPOOL_FREE(pool, addr) \
4672 {unsigned int _qzz_res; \
4673 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4674 VG_USERREQ__MEMPOOL_FREE, \
sewardj9af10a12006-02-01 14:59:42 +00004675 pool, addr, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004676 }
4677
sewardj2c1c9df2006-07-28 00:06:37 +00004678/* Disassociate any pieces outside a particular range. */
4679#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
4680 {unsigned int _qzz_res; \
4681 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4682 VG_USERREQ__MEMPOOL_TRIM, \
4683 pool, addr, size, 0, 0); \
4684 }
4685
sewardjc740d762006-10-05 17:59:23 +00004686/* Resize and/or move a piece associated with a memory pool. */
4687#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
4688 {unsigned int _qzz_res; \
4689 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4690 VG_USERREQ__MOVE_MEMPOOL, \
4691 poolA, poolB, 0, 0, 0); \
4692 }
4693
4694/* Resize and/or move a piece associated with a memory pool. */
4695#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
4696 {unsigned int _qzz_res; \
4697 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4698 VG_USERREQ__MEMPOOL_CHANGE, \
4699 pool, addrA, addrB, size, 0); \
4700 }
4701
4702/* Return 1 if a mempool exists, else 0. */
4703#define VALGRIND_MEMPOOL_EXISTS(pool) \
njn44862972009-02-23 02:08:24 +00004704 __extension__ \
sewardjc740d762006-10-05 17:59:23 +00004705 ({unsigned int _qzz_res; \
4706 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4707 VG_USERREQ__MEMPOOL_EXISTS, \
4708 pool, 0, 0, 0, 0); \
4709 _qzz_res; \
4710 })
4711
rjwalsh0140af52005-06-04 20:42:33 +00004712/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004713#define VALGRIND_STACK_REGISTER(start, end) \
njn44862972009-02-23 02:08:24 +00004714 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004715 ({unsigned int _qzz_res; \
4716 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4717 VG_USERREQ__STACK_REGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00004718 start, end, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004719 _qzz_res; \
rjwalsh0140af52005-06-04 20:42:33 +00004720 })
4721
4722/* Unmark the piece of memory associated with a stack id as being a
4723 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00004724#define VALGRIND_STACK_DEREGISTER(id) \
4725 {unsigned int _qzz_res; \
4726 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4727 VG_USERREQ__STACK_DEREGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00004728 id, 0, 0, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00004729 }
4730
4731/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004732#define VALGRIND_STACK_CHANGE(id, start, end) \
4733 {unsigned int _qzz_res; \
4734 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4735 VG_USERREQ__STACK_CHANGE, \
sewardj9af10a12006-02-01 14:59:42 +00004736 id, start, end, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00004737 }
4738
sewardjc8259b82009-04-22 22:42:10 +00004739/* Load PDB debug info for Wine PE image_map. */
4740#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
4741 {unsigned int _qzz_res; \
4742 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4743 VG_USERREQ__LOAD_PDB_DEBUGINFO, \
4744 fd, ptr, total_size, delta, 0); \
4745 }
4746
sewardj5c659622010-08-20 18:22:07 +00004747/* Map a code address to a source file name and line number. buf64
4748 must point to a 64-byte buffer in the caller's address space. The
4749 result will be dumped in there and is guaranteed to be zero
4750 terminated. If no info is found, the first byte is set to zero. */
4751#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \
4752 {unsigned int _qzz_res; \
4753 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4754 VG_USERREQ__MAP_IP_TO_SRCLOC, \
4755 addr, buf64, 0, 0, 0); \
4756 }
4757
sewardj0ec07f32006-01-12 12:32:32 +00004758
sewardjf5c1a7f2006-10-17 01:32:48 +00004759#undef PLAT_x86_linux
4760#undef PLAT_amd64_linux
4761#undef PLAT_ppc32_linux
4762#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +00004763#undef PLAT_arm_linux
sewardjf5c1a7f2006-10-17 01:32:48 +00004764#undef PLAT_ppc32_aix5
4765#undef PLAT_ppc64_aix5
sewardj0ec07f32006-01-12 12:32:32 +00004766
njn3e884182003-04-15 13:03:23 +00004767#endif /* __VALGRIND_H */