blob: b178cda9a6d631cacc54f6c32d4f66362047ee0e [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
njn9f207462009-03-10 22:02:09 +000015 Copyright (C) 2000-2009 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
fitzhardinge39de4b42003-10-31 07:12:21 +000076#include <stdarg.h>
77
njn3dd0a912005-06-28 19:44:10 +000078/* Nb: this file might be included in a file compiled with -ansi. So
79 we can't use C++ style "//" comments nor the "asm" keyword (instead
80 use "__asm__"). */
81
sewardjf5c1a7f2006-10-17 01:32:48 +000082/* Derive some tags indicating what the target platform is. Note
sewardj0ec07f32006-01-12 12:32:32 +000083 that in this file we're using the compiler's CPP symbols for
84 identifying architectures, which are different to the ones we use
85 within the rest of Valgrind. Note, __powerpc__ is active for both
86 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
sewardj59570ff2010-01-01 11:59:33 +000087 latter (on Linux, that is).
88
89 Misc note: how to find out what's predefined in gcc by default:
90 gcc -Wp,-dM somefile.c
91*/
sewardjf5c1a7f2006-10-17 01:32:48 +000092#undef PLAT_x86_linux
93#undef PLAT_amd64_linux
94#undef PLAT_ppc32_linux
95#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +000096#undef PLAT_arm_linux
sewardjf5c1a7f2006-10-17 01:32:48 +000097#undef PLAT_ppc32_aix5
98#undef PLAT_ppc64_aix5
sewardj0ec07f32006-01-12 12:32:32 +000099
njnf76d27a2009-05-28 01:53:07 +0000100#if defined(_AIX) && defined(__64BIT__)
sewardjf5c1a7f2006-10-17 01:32:48 +0000101# define PLAT_ppc64_aix5 1
102#elif defined(_AIX) && !defined(__64BIT__)
103# define PLAT_ppc32_aix5 1
njnf76d27a2009-05-28 01:53:07 +0000104#elif defined(__APPLE__) && defined(__i386__)
105# define PLAT_x86_darwin 1
106#elif defined(__APPLE__) && defined(__x86_64__)
107# define PLAT_amd64_darwin 1
sewardj59570ff2010-01-01 11:59:33 +0000108#elif defined(__linux__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000109# define PLAT_x86_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000110#elif defined(__linux__) && defined(__x86_64__)
njnf76d27a2009-05-28 01:53:07 +0000111# define PLAT_amd64_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000112#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000113# define PLAT_ppc32_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000114#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000115# define PLAT_ppc64_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000116#elif defined(__linux__) && defined(__arm__)
117# define PLAT_arm_linux 1
njnf76d27a2009-05-28 01:53:07 +0000118#else
sewardjf5c1a7f2006-10-17 01:32:48 +0000119/* If we're not compiling for our target platform, don't generate
sewardj0ec07f32006-01-12 12:32:32 +0000120 any inline asms. */
sewardj0ec07f32006-01-12 12:32:32 +0000121# if !defined(NVALGRIND)
122# define NVALGRIND 1
123# endif
124#endif
125
126
njn30d76c62005-06-18 15:07:39 +0000127/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000128/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
129/* in here of use to end-users -- skip to the next section. */
njn30d76c62005-06-18 15:07:39 +0000130/* ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000131
sewardj0ec07f32006-01-12 12:32:32 +0000132#if defined(NVALGRIND)
njn26aba4d2005-05-16 13:31:23 +0000133
134/* Define NVALGRIND to completely remove the Valgrind magic sequence
sewardj0ec07f32006-01-12 12:32:32 +0000135 from the compiled code (analogous to NDEBUG's effects on
136 assert()) */
137#define VALGRIND_DO_CLIENT_REQUEST( \
138 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000139 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000140 { \
141 (_zzq_rlval) = (_zzq_default); \
njn26aba4d2005-05-16 13:31:23 +0000142 }
143
sewardj0ec07f32006-01-12 12:32:32 +0000144#else /* ! NVALGRIND */
nethercotee90c6832004-10-18 18:07:49 +0000145
sewardj0ec07f32006-01-12 12:32:32 +0000146/* The following defines the magic code sequences which the JITter
147 spots and handles magically. Don't look too closely at them as
148 they will rot your brain.
149
150 The assembly code sequences for all architectures is in this one
151 file. This is because this file must be stand-alone, and we don't
152 want to have multiple files.
153
154 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
155 value gets put in the return slot, so that everything works when
156 this is executed not under Valgrind. Args are passed in a memory
157 block, and so there's no intrinsic limit to the number that could
sewardj9af10a12006-02-01 14:59:42 +0000158 be passed, but it's currently five.
nethercotee90c6832004-10-18 18:07:49 +0000159
nethercote54265442004-10-26 12:56:58 +0000160 The macro args are:
161 _zzq_rlval result lvalue
162 _zzq_default default value (result returned when running on real CPU)
163 _zzq_request request code
sewardj9af10a12006-02-01 14:59:42 +0000164 _zzq_arg1..5 request params
nethercote54265442004-10-26 12:56:58 +0000165
sewardj0ec07f32006-01-12 12:32:32 +0000166 The other two macros are used to support function wrapping, and are
sewardjd68ac3e2006-01-20 14:31:57 +0000167 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
168 guest's NRADDR pseudo-register and whatever other information is
169 needed to safely run the call original from the wrapper: on
170 ppc64-linux, the R2 value at the divert point is also needed. This
171 information is abstracted into a user-visible type, OrigFn.
172
173 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
174 guest, but guarantees that the branch instruction will not be
175 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
176 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
177 complete inline asm, since it needs to be combined with more magic
178 inline asm stuff to be useful.
nethercotee90c6832004-10-18 18:07:49 +0000179*/
180
njnf76d27a2009-05-28 01:53:07 +0000181/* ------------------------- x86-{linux,darwin} ---------------- */
sewardjde4a4ab2005-03-23 13:10:32 +0000182
njnf76d27a2009-05-28 01:53:07 +0000183#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
sewardjc8858442006-01-20 15:17:20 +0000184
185typedef
186 struct {
187 unsigned int nraddr; /* where's the code? */
188 }
189 OrigFn;
190
sewardj0ec07f32006-01-12 12:32:32 +0000191#define __SPECIAL_INSTRUCTION_PREAMBLE \
192 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000193 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000194
sewardj0ec07f32006-01-12 12:32:32 +0000195#define VALGRIND_DO_CLIENT_REQUEST( \
196 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000197 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
198 { volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000199 volatile unsigned int _zzq_result; \
200 _zzq_args[0] = (unsigned int)(_zzq_request); \
201 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
202 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
203 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
204 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000205 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000206 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
207 /* %EDX = client_request ( %EAX ) */ \
208 "xchgl %%ebx,%%ebx" \
209 : "=d" (_zzq_result) \
210 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
211 : "cc", "memory" \
212 ); \
213 _zzq_rlval = _zzq_result; \
cerion85665ca2005-06-20 15:51:07 +0000214 }
sewardj2c48c7b2005-11-29 13:05:56 +0000215
sewardjc8858442006-01-20 15:17:20 +0000216#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
217 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
218 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000219 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
220 /* %EAX = guest_NRADDR */ \
221 "xchgl %%ecx,%%ecx" \
222 : "=a" (__addr) \
223 : \
224 : "cc", "memory" \
225 ); \
sewardjc8858442006-01-20 15:17:20 +0000226 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000227 }
sewardj0ec07f32006-01-12 12:32:32 +0000228
229#define VALGRIND_CALL_NOREDIR_EAX \
230 __SPECIAL_INSTRUCTION_PREAMBLE \
231 /* call-noredir *%EAX */ \
232 "xchgl %%edx,%%edx\n\t"
njnf76d27a2009-05-28 01:53:07 +0000233#endif /* PLAT_x86_linux || PLAT_x86_darwin */
sewardj0ec07f32006-01-12 12:32:32 +0000234
njnf76d27a2009-05-28 01:53:07 +0000235/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000236
njnf76d27a2009-05-28 01:53:07 +0000237#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardjc8858442006-01-20 15:17:20 +0000238
239typedef
240 struct {
241 unsigned long long int nraddr; /* where's the code? */
242 }
243 OrigFn;
244
sewardj0ec07f32006-01-12 12:32:32 +0000245#define __SPECIAL_INSTRUCTION_PREAMBLE \
246 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000247 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000248
249#define VALGRIND_DO_CLIENT_REQUEST( \
250 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000251 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
252 { volatile unsigned long long int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000253 volatile unsigned long long int _zzq_result; \
254 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
255 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
256 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
257 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
258 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000259 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000260 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
261 /* %RDX = client_request ( %RAX ) */ \
262 "xchgq %%rbx,%%rbx" \
263 : "=d" (_zzq_result) \
264 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
265 : "cc", "memory" \
266 ); \
267 _zzq_rlval = _zzq_result; \
268 }
269
sewardjc8858442006-01-20 15:17:20 +0000270#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
271 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
272 volatile unsigned long long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000273 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
274 /* %RAX = guest_NRADDR */ \
275 "xchgq %%rcx,%%rcx" \
276 : "=a" (__addr) \
277 : \
278 : "cc", "memory" \
279 ); \
sewardjc8858442006-01-20 15:17:20 +0000280 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000281 }
282
283#define VALGRIND_CALL_NOREDIR_RAX \
284 __SPECIAL_INSTRUCTION_PREAMBLE \
285 /* call-noredir *%RAX */ \
286 "xchgq %%rdx,%%rdx\n\t"
njnf76d27a2009-05-28 01:53:07 +0000287#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +0000288
sewardjf5c1a7f2006-10-17 01:32:48 +0000289/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000290
sewardjf5c1a7f2006-10-17 01:32:48 +0000291#if defined(PLAT_ppc32_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000292
293typedef
294 struct {
sewardjc8858442006-01-20 15:17:20 +0000295 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000296 }
297 OrigFn;
298
sewardj0ec07f32006-01-12 12:32:32 +0000299#define __SPECIAL_INSTRUCTION_PREAMBLE \
300 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000301 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000302
303#define VALGRIND_DO_CLIENT_REQUEST( \
304 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000305 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000306 \
sewardj9af10a12006-02-01 14:59:42 +0000307 { unsigned int _zzq_args[6]; \
sewardj1c5bcb12006-12-08 21:29:46 +0000308 unsigned int _zzq_result; \
309 unsigned int* _zzq_ptr; \
sewardj0ec07f32006-01-12 12:32:32 +0000310 _zzq_args[0] = (unsigned int)(_zzq_request); \
311 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
312 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
313 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
314 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000315 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000316 _zzq_ptr = _zzq_args; \
sewardj1c5bcb12006-12-08 21:29:46 +0000317 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
318 "mr 4,%2\n\t" /*ptr*/ \
319 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj0ec07f32006-01-12 12:32:32 +0000320 /* %R3 = client_request ( %R4 ) */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000321 "or 1,1,1\n\t" \
322 "mr %0,3" /*result*/ \
323 : "=b" (_zzq_result) \
324 : "b" (_zzq_default), "b" (_zzq_ptr) \
325 : "cc", "memory", "r3", "r4"); \
sewardj0ec07f32006-01-12 12:32:32 +0000326 _zzq_rlval = _zzq_result; \
327 }
328
sewardjd68ac3e2006-01-20 14:31:57 +0000329#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
330 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj1c5bcb12006-12-08 21:29:46 +0000331 unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000332 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
333 /* %R3 = guest_NRADDR */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000334 "or 2,2,2\n\t" \
335 "mr %0,3" \
336 : "=b" (__addr) \
sewardj0ec07f32006-01-12 12:32:32 +0000337 : \
sewardj1c5bcb12006-12-08 21:29:46 +0000338 : "cc", "memory", "r3" \
sewardj0ec07f32006-01-12 12:32:32 +0000339 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000340 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000341 }
342
343#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
344 __SPECIAL_INSTRUCTION_PREAMBLE \
345 /* branch-and-link-to-noredir *%R11 */ \
346 "or 3,3,3\n\t"
sewardjf5c1a7f2006-10-17 01:32:48 +0000347#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000348
sewardjf5c1a7f2006-10-17 01:32:48 +0000349/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000350
sewardjf5c1a7f2006-10-17 01:32:48 +0000351#if defined(PLAT_ppc64_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000352
353typedef
354 struct {
355 unsigned long long int nraddr; /* where's the code? */
356 unsigned long long int r2; /* what tocptr do we need? */
357 }
358 OrigFn;
359
sewardj1a85f4f2006-01-12 21:15:35 +0000360#define __SPECIAL_INSTRUCTION_PREAMBLE \
361 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
362 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
363
sewardj0ec07f32006-01-12 12:32:32 +0000364#define VALGRIND_DO_CLIENT_REQUEST( \
365 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000366 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000367 \
sewardj9af10a12006-02-01 14:59:42 +0000368 { unsigned long long int _zzq_args[6]; \
sewardj1a85f4f2006-01-12 21:15:35 +0000369 register unsigned long long int _zzq_result __asm__("r3"); \
370 register unsigned long long int* _zzq_ptr __asm__("r4"); \
371 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
372 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
373 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
374 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
375 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000376 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000377 _zzq_ptr = _zzq_args; \
sewardj1a85f4f2006-01-12 21:15:35 +0000378 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
379 /* %R3 = client_request ( %R4 ) */ \
380 "or 1,1,1" \
381 : "=r" (_zzq_result) \
sewardj0ec07f32006-01-12 12:32:32 +0000382 : "0" (_zzq_default), "r" (_zzq_ptr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000383 : "cc", "memory"); \
384 _zzq_rlval = _zzq_result; \
sewardj0ec07f32006-01-12 12:32:32 +0000385 }
sewardj1a85f4f2006-01-12 21:15:35 +0000386
sewardjd68ac3e2006-01-20 14:31:57 +0000387#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
388 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
389 register unsigned long long int __addr __asm__("r3"); \
sewardj1a85f4f2006-01-12 21:15:35 +0000390 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
391 /* %R3 = guest_NRADDR */ \
392 "or 2,2,2" \
393 : "=r" (__addr) \
394 : \
395 : "cc", "memory" \
396 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000397 _zzq_orig->nraddr = __addr; \
398 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
399 /* %R3 = guest_NRADDR_GPR2 */ \
400 "or 4,4,4" \
401 : "=r" (__addr) \
402 : \
403 : "cc", "memory" \
404 ); \
405 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000406 }
407
408#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
409 __SPECIAL_INSTRUCTION_PREAMBLE \
410 /* branch-and-link-to-noredir *%R11 */ \
411 "or 3,3,3\n\t"
412
sewardjf5c1a7f2006-10-17 01:32:48 +0000413#endif /* PLAT_ppc64_linux */
cerion85665ca2005-06-20 15:51:07 +0000414
sewardj59570ff2010-01-01 11:59:33 +0000415/* ------------------------- arm-linux ------------------------- */
416
417#if defined(PLAT_arm_linux)
418
419typedef
420 struct {
421 unsigned int nraddr; /* where's the code? */
422 }
423 OrigFn;
424
425#define __SPECIAL_INSTRUCTION_PREAMBLE \
426 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
427 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
428
429#define VALGRIND_DO_CLIENT_REQUEST( \
430 _zzq_rlval, _zzq_default, _zzq_request, \
431 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
432 \
433 { volatile unsigned int _zzq_args[6]; \
434 volatile unsigned int _zzq_result; \
435 _zzq_args[0] = (unsigned int)(_zzq_request); \
436 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
437 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
438 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
439 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
440 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
441 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
442 "mov r4, %2\n\t" /*ptr*/ \
443 __SPECIAL_INSTRUCTION_PREAMBLE \
444 /* R3 = client_request ( R4 ) */ \
445 "orr r10, r10, r10\n\t" \
446 "mov %0, r3" /*result*/ \
447 : "=r" (_zzq_result) \
448 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
449 : "cc","memory", "r3", "r4"); \
450 _zzq_rlval = _zzq_result; \
451 }
452
453#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
454 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
455 unsigned int __addr; \
456 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
457 /* R3 = guest_NRADDR */ \
458 "orr r11, r11, r11\n\t" \
459 "mov %0, r3" \
460 : "=r" (__addr) \
461 : \
462 : "cc", "memory", "r3" \
463 ); \
464 _zzq_orig->nraddr = __addr; \
465 }
466
467#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
468 __SPECIAL_INSTRUCTION_PREAMBLE \
469 /* branch-and-link-to-noredir *%R4 */ \
470 "orr r12, r12, r12\n\t"
471
472#endif /* PLAT_arm_linux */
473
sewardjf5c1a7f2006-10-17 01:32:48 +0000474/* ------------------------ ppc32-aix5 ------------------------- */
475
476#if defined(PLAT_ppc32_aix5)
477
478typedef
479 struct {
480 unsigned int nraddr; /* where's the code? */
481 unsigned int r2; /* what tocptr do we need? */
482 }
483 OrigFn;
484
485#define __SPECIAL_INSTRUCTION_PREAMBLE \
486 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
487 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
488
489#define VALGRIND_DO_CLIENT_REQUEST( \
490 _zzq_rlval, _zzq_default, _zzq_request, \
491 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
492 \
493 { unsigned int _zzq_args[7]; \
494 register unsigned int _zzq_result; \
495 register unsigned int* _zzq_ptr; \
496 _zzq_args[0] = (unsigned int)(_zzq_request); \
497 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
498 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
499 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
500 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
501 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
502 _zzq_args[6] = (unsigned int)(_zzq_default); \
503 _zzq_ptr = _zzq_args; \
504 __asm__ volatile("mr 4,%1\n\t" \
505 "lwz 3, 24(4)\n\t" \
506 __SPECIAL_INSTRUCTION_PREAMBLE \
507 /* %R3 = client_request ( %R4 ) */ \
508 "or 1,1,1\n\t" \
509 "mr %0,3" \
510 : "=b" (_zzq_result) \
511 : "b" (_zzq_ptr) \
512 : "r3", "r4", "cc", "memory"); \
513 _zzq_rlval = _zzq_result; \
514 }
515
516#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
517 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
518 register unsigned int __addr; \
519 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
520 /* %R3 = guest_NRADDR */ \
521 "or 2,2,2\n\t" \
522 "mr %0,3" \
523 : "=b" (__addr) \
524 : \
525 : "r3", "cc", "memory" \
526 ); \
527 _zzq_orig->nraddr = __addr; \
528 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
529 /* %R3 = guest_NRADDR_GPR2 */ \
530 "or 4,4,4\n\t" \
531 "mr %0,3" \
532 : "=b" (__addr) \
533 : \
534 : "r3", "cc", "memory" \
535 ); \
536 _zzq_orig->r2 = __addr; \
537 }
538
539#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
540 __SPECIAL_INSTRUCTION_PREAMBLE \
541 /* branch-and-link-to-noredir *%R11 */ \
542 "or 3,3,3\n\t"
543
544#endif /* PLAT_ppc32_aix5 */
545
546/* ------------------------ ppc64-aix5 ------------------------- */
547
548#if defined(PLAT_ppc64_aix5)
549
550typedef
551 struct {
552 unsigned long long int nraddr; /* where's the code? */
553 unsigned long long int r2; /* what tocptr do we need? */
554 }
555 OrigFn;
556
557#define __SPECIAL_INSTRUCTION_PREAMBLE \
558 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
559 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
560
561#define VALGRIND_DO_CLIENT_REQUEST( \
562 _zzq_rlval, _zzq_default, _zzq_request, \
563 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
564 \
565 { unsigned long long int _zzq_args[7]; \
566 register unsigned long long int _zzq_result; \
567 register unsigned long long int* _zzq_ptr; \
568 _zzq_args[0] = (unsigned int long long)(_zzq_request); \
569 _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
570 _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
571 _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
572 _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
573 _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
574 _zzq_args[6] = (unsigned int long long)(_zzq_default); \
575 _zzq_ptr = _zzq_args; \
576 __asm__ volatile("mr 4,%1\n\t" \
577 "ld 3, 48(4)\n\t" \
578 __SPECIAL_INSTRUCTION_PREAMBLE \
579 /* %R3 = client_request ( %R4 ) */ \
580 "or 1,1,1\n\t" \
581 "mr %0,3" \
582 : "=b" (_zzq_result) \
583 : "b" (_zzq_ptr) \
584 : "r3", "r4", "cc", "memory"); \
585 _zzq_rlval = _zzq_result; \
586 }
587
588#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
589 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
590 register unsigned long long int __addr; \
591 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
592 /* %R3 = guest_NRADDR */ \
593 "or 2,2,2\n\t" \
594 "mr %0,3" \
595 : "=b" (__addr) \
596 : \
597 : "r3", "cc", "memory" \
598 ); \
599 _zzq_orig->nraddr = __addr; \
600 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
601 /* %R3 = guest_NRADDR_GPR2 */ \
602 "or 4,4,4\n\t" \
603 "mr %0,3" \
604 : "=b" (__addr) \
605 : \
606 : "r3", "cc", "memory" \
607 ); \
608 _zzq_orig->r2 = __addr; \
609 }
610
611#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
612 __SPECIAL_INSTRUCTION_PREAMBLE \
613 /* branch-and-link-to-noredir *%R11 */ \
614 "or 3,3,3\n\t"
615
616#endif /* PLAT_ppc64_aix5 */
617
618/* Insert assembly code for other platforms here... */
njn26aba4d2005-05-16 13:31:23 +0000619
sewardj37091fb2002-11-16 11:06:50 +0000620#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +0000621
nethercote69d9c462004-10-26 13:00:12 +0000622
njn30d76c62005-06-18 15:07:39 +0000623/* ------------------------------------------------------------------ */
sewardjf5c1a7f2006-10-17 01:32:48 +0000624/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
sewardj0ec07f32006-01-12 12:32:32 +0000625/* ugly. It's the least-worst tradeoff I can think of. */
626/* ------------------------------------------------------------------ */
627
628/* This section defines magic (a.k.a appalling-hack) macros for doing
629 guaranteed-no-redirection macros, so as to get from function
630 wrappers to the functions they are wrapping. The whole point is to
631 construct standard call sequences, but to do the call itself with a
632 special no-redirect call pseudo-instruction that the JIT
633 understands and handles specially. This section is long and
634 repetitious, and I can't see a way to make it shorter.
635
636 The naming scheme is as follows:
637
638 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
639
640 'W' stands for "word" and 'v' for "void". Hence there are
641 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
642 and for each, the possibility of returning a word-typed result, or
643 no result.
644*/
645
646/* Use these to write the name of your wrapper. NOTE: duplicates
647 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
648
njn5f5ef2a2009-05-11 08:01:09 +0000649/* Use an extra level of macroisation so as to ensure the soname/fnname
650 args are fully macro-expanded before pasting them together. */
651#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
652
sewardj0ec07f32006-01-12 12:32:32 +0000653#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
njn5f5ef2a2009-05-11 08:01:09 +0000654 VG_CONCAT4(_vgwZU_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000655
656#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
njn5f5ef2a2009-05-11 08:01:09 +0000657 VG_CONCAT4(_vgwZZ_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000658
sewardjd68ac3e2006-01-20 14:31:57 +0000659/* Use this macro from within a wrapper function to collect the
660 context (address and possibly other info) of the original function.
661 Once you have that you can then use it in one of the CALL_FN_
662 macros. The type of the argument _lval is OrigFn. */
663#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +0000664
665/* Derivatives of the main macros below, for calling functions
666 returning void. */
667
668#define CALL_FN_v_v(fnptr) \
669 do { volatile unsigned long _junk; \
670 CALL_FN_W_v(_junk,fnptr); } while (0)
671
672#define CALL_FN_v_W(fnptr, arg1) \
673 do { volatile unsigned long _junk; \
674 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
675
676#define CALL_FN_v_WW(fnptr, arg1,arg2) \
677 do { volatile unsigned long _junk; \
678 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
679
sewardj5ce4b152006-03-11 12:57:41 +0000680#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
681 do { volatile unsigned long _junk; \
682 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
683
njn2b5f0a92009-05-19 01:24:50 +0000684#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
685 do { volatile unsigned long _junk; \
686 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
687
688#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
689 do { volatile unsigned long _junk; \
690 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
691
692#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
693 do { volatile unsigned long _junk; \
694 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
695
696#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
697 do { volatile unsigned long _junk; \
698 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
699
njnf76d27a2009-05-28 01:53:07 +0000700/* ------------------------- x86-{linux,darwin} ---------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000701
njnf76d27a2009-05-28 01:53:07 +0000702#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
sewardj0ec07f32006-01-12 12:32:32 +0000703
704/* These regs are trashed by the hidden call. No need to mention eax
705 as gcc can already see that, plus causes gcc to bomb. */
706#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
707
708/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
709 long) == 4. */
710
sewardj66226cc2006-01-20 15:46:46 +0000711#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +0000712 do { \
sewardj66226cc2006-01-20 15:46:46 +0000713 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000714 volatile unsigned long _argvec[1]; \
715 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000716 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000717 __asm__ volatile( \
718 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
719 VALGRIND_CALL_NOREDIR_EAX \
720 : /*out*/ "=a" (_res) \
721 : /*in*/ "a" (&_argvec[0]) \
722 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
723 ); \
724 lval = (__typeof__(lval)) _res; \
725 } while (0)
726
sewardj66226cc2006-01-20 15:46:46 +0000727#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +0000728 do { \
sewardj66226cc2006-01-20 15:46:46 +0000729 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000730 volatile unsigned long _argvec[2]; \
731 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000732 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000733 _argvec[1] = (unsigned long)(arg1); \
734 __asm__ volatile( \
735 "pushl 4(%%eax)\n\t" \
736 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
737 VALGRIND_CALL_NOREDIR_EAX \
738 "addl $4, %%esp\n" \
739 : /*out*/ "=a" (_res) \
740 : /*in*/ "a" (&_argvec[0]) \
741 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
742 ); \
743 lval = (__typeof__(lval)) _res; \
744 } while (0)
745
sewardj66226cc2006-01-20 15:46:46 +0000746#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +0000747 do { \
sewardj66226cc2006-01-20 15:46:46 +0000748 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000749 volatile unsigned long _argvec[3]; \
750 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000751 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000752 _argvec[1] = (unsigned long)(arg1); \
753 _argvec[2] = (unsigned long)(arg2); \
754 __asm__ volatile( \
755 "pushl 8(%%eax)\n\t" \
756 "pushl 4(%%eax)\n\t" \
757 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
758 VALGRIND_CALL_NOREDIR_EAX \
759 "addl $8, %%esp\n" \
760 : /*out*/ "=a" (_res) \
761 : /*in*/ "a" (&_argvec[0]) \
762 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
763 ); \
764 lval = (__typeof__(lval)) _res; \
765 } while (0)
766
sewardj9e8b07a2006-02-18 21:13:29 +0000767#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
768 do { \
769 volatile OrigFn _orig = (orig); \
770 volatile unsigned long _argvec[4]; \
771 volatile unsigned long _res; \
772 _argvec[0] = (unsigned long)_orig.nraddr; \
773 _argvec[1] = (unsigned long)(arg1); \
774 _argvec[2] = (unsigned long)(arg2); \
775 _argvec[3] = (unsigned long)(arg3); \
776 __asm__ volatile( \
777 "pushl 12(%%eax)\n\t" \
778 "pushl 8(%%eax)\n\t" \
779 "pushl 4(%%eax)\n\t" \
780 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
781 VALGRIND_CALL_NOREDIR_EAX \
782 "addl $12, %%esp\n" \
783 : /*out*/ "=a" (_res) \
784 : /*in*/ "a" (&_argvec[0]) \
785 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
786 ); \
787 lval = (__typeof__(lval)) _res; \
788 } while (0)
789
sewardj66226cc2006-01-20 15:46:46 +0000790#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
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[5]; \
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 _argvec[1] = (unsigned long)(arg1); \
797 _argvec[2] = (unsigned long)(arg2); \
798 _argvec[3] = (unsigned long)(arg3); \
799 _argvec[4] = (unsigned long)(arg4); \
800 __asm__ volatile( \
801 "pushl 16(%%eax)\n\t" \
802 "pushl 12(%%eax)\n\t" \
803 "pushl 8(%%eax)\n\t" \
804 "pushl 4(%%eax)\n\t" \
805 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
806 VALGRIND_CALL_NOREDIR_EAX \
807 "addl $16, %%esp\n" \
808 : /*out*/ "=a" (_res) \
809 : /*in*/ "a" (&_argvec[0]) \
810 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
811 ); \
812 lval = (__typeof__(lval)) _res; \
813 } while (0)
814
sewardj66226cc2006-01-20 15:46:46 +0000815#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000816 do { \
sewardj66226cc2006-01-20 15:46:46 +0000817 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000818 volatile unsigned long _argvec[6]; \
819 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000820 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000821 _argvec[1] = (unsigned long)(arg1); \
822 _argvec[2] = (unsigned long)(arg2); \
823 _argvec[3] = (unsigned long)(arg3); \
824 _argvec[4] = (unsigned long)(arg4); \
825 _argvec[5] = (unsigned long)(arg5); \
826 __asm__ volatile( \
827 "pushl 20(%%eax)\n\t" \
828 "pushl 16(%%eax)\n\t" \
829 "pushl 12(%%eax)\n\t" \
830 "pushl 8(%%eax)\n\t" \
831 "pushl 4(%%eax)\n\t" \
832 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
833 VALGRIND_CALL_NOREDIR_EAX \
834 "addl $20, %%esp\n" \
835 : /*out*/ "=a" (_res) \
836 : /*in*/ "a" (&_argvec[0]) \
837 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
838 ); \
839 lval = (__typeof__(lval)) _res; \
840 } while (0)
841
sewardj66226cc2006-01-20 15:46:46 +0000842#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +0000843 do { \
sewardj66226cc2006-01-20 15:46:46 +0000844 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000845 volatile unsigned long _argvec[7]; \
846 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000847 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000848 _argvec[1] = (unsigned long)(arg1); \
849 _argvec[2] = (unsigned long)(arg2); \
850 _argvec[3] = (unsigned long)(arg3); \
851 _argvec[4] = (unsigned long)(arg4); \
852 _argvec[5] = (unsigned long)(arg5); \
853 _argvec[6] = (unsigned long)(arg6); \
854 __asm__ volatile( \
855 "pushl 24(%%eax)\n\t" \
856 "pushl 20(%%eax)\n\t" \
857 "pushl 16(%%eax)\n\t" \
858 "pushl 12(%%eax)\n\t" \
859 "pushl 8(%%eax)\n\t" \
860 "pushl 4(%%eax)\n\t" \
861 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
862 VALGRIND_CALL_NOREDIR_EAX \
863 "addl $24, %%esp\n" \
864 : /*out*/ "=a" (_res) \
865 : /*in*/ "a" (&_argvec[0]) \
866 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
867 ); \
868 lval = (__typeof__(lval)) _res; \
869 } while (0)
870
sewardj66226cc2006-01-20 15:46:46 +0000871#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
872 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +0000873 do { \
sewardj66226cc2006-01-20 15:46:46 +0000874 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000875 volatile unsigned long _argvec[8]; \
876 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000877 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000878 _argvec[1] = (unsigned long)(arg1); \
879 _argvec[2] = (unsigned long)(arg2); \
880 _argvec[3] = (unsigned long)(arg3); \
881 _argvec[4] = (unsigned long)(arg4); \
882 _argvec[5] = (unsigned long)(arg5); \
883 _argvec[6] = (unsigned long)(arg6); \
884 _argvec[7] = (unsigned long)(arg7); \
885 __asm__ volatile( \
886 "pushl 28(%%eax)\n\t" \
887 "pushl 24(%%eax)\n\t" \
888 "pushl 20(%%eax)\n\t" \
889 "pushl 16(%%eax)\n\t" \
890 "pushl 12(%%eax)\n\t" \
891 "pushl 8(%%eax)\n\t" \
892 "pushl 4(%%eax)\n\t" \
893 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
894 VALGRIND_CALL_NOREDIR_EAX \
895 "addl $28, %%esp\n" \
896 : /*out*/ "=a" (_res) \
897 : /*in*/ "a" (&_argvec[0]) \
898 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
899 ); \
900 lval = (__typeof__(lval)) _res; \
901 } while (0)
902
sewardj66226cc2006-01-20 15:46:46 +0000903#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
904 arg7,arg8) \
sewardj0ec07f32006-01-12 12:32:32 +0000905 do { \
sewardj66226cc2006-01-20 15:46:46 +0000906 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000907 volatile unsigned long _argvec[9]; \
908 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000909 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000910 _argvec[1] = (unsigned long)(arg1); \
911 _argvec[2] = (unsigned long)(arg2); \
912 _argvec[3] = (unsigned long)(arg3); \
913 _argvec[4] = (unsigned long)(arg4); \
914 _argvec[5] = (unsigned long)(arg5); \
915 _argvec[6] = (unsigned long)(arg6); \
916 _argvec[7] = (unsigned long)(arg7); \
917 _argvec[8] = (unsigned long)(arg8); \
918 __asm__ volatile( \
919 "pushl 32(%%eax)\n\t" \
920 "pushl 28(%%eax)\n\t" \
921 "pushl 24(%%eax)\n\t" \
922 "pushl 20(%%eax)\n\t" \
923 "pushl 16(%%eax)\n\t" \
924 "pushl 12(%%eax)\n\t" \
925 "pushl 8(%%eax)\n\t" \
926 "pushl 4(%%eax)\n\t" \
927 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
928 VALGRIND_CALL_NOREDIR_EAX \
929 "addl $32, %%esp\n" \
930 : /*out*/ "=a" (_res) \
931 : /*in*/ "a" (&_argvec[0]) \
932 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
933 ); \
934 lval = (__typeof__(lval)) _res; \
935 } while (0)
936
sewardj45fa5b02006-03-09 19:06:23 +0000937#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
938 arg7,arg8,arg9) \
939 do { \
940 volatile OrigFn _orig = (orig); \
941 volatile unsigned long _argvec[10]; \
942 volatile unsigned long _res; \
943 _argvec[0] = (unsigned long)_orig.nraddr; \
944 _argvec[1] = (unsigned long)(arg1); \
945 _argvec[2] = (unsigned long)(arg2); \
946 _argvec[3] = (unsigned long)(arg3); \
947 _argvec[4] = (unsigned long)(arg4); \
948 _argvec[5] = (unsigned long)(arg5); \
949 _argvec[6] = (unsigned long)(arg6); \
950 _argvec[7] = (unsigned long)(arg7); \
951 _argvec[8] = (unsigned long)(arg8); \
952 _argvec[9] = (unsigned long)(arg9); \
953 __asm__ volatile( \
954 "pushl 36(%%eax)\n\t" \
955 "pushl 32(%%eax)\n\t" \
956 "pushl 28(%%eax)\n\t" \
957 "pushl 24(%%eax)\n\t" \
958 "pushl 20(%%eax)\n\t" \
959 "pushl 16(%%eax)\n\t" \
960 "pushl 12(%%eax)\n\t" \
961 "pushl 8(%%eax)\n\t" \
962 "pushl 4(%%eax)\n\t" \
963 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
964 VALGRIND_CALL_NOREDIR_EAX \
965 "addl $36, %%esp\n" \
966 : /*out*/ "=a" (_res) \
967 : /*in*/ "a" (&_argvec[0]) \
968 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
969 ); \
970 lval = (__typeof__(lval)) _res; \
971 } while (0)
972
973#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
974 arg7,arg8,arg9,arg10) \
975 do { \
976 volatile OrigFn _orig = (orig); \
977 volatile unsigned long _argvec[11]; \
978 volatile unsigned long _res; \
979 _argvec[0] = (unsigned long)_orig.nraddr; \
980 _argvec[1] = (unsigned long)(arg1); \
981 _argvec[2] = (unsigned long)(arg2); \
982 _argvec[3] = (unsigned long)(arg3); \
983 _argvec[4] = (unsigned long)(arg4); \
984 _argvec[5] = (unsigned long)(arg5); \
985 _argvec[6] = (unsigned long)(arg6); \
986 _argvec[7] = (unsigned long)(arg7); \
987 _argvec[8] = (unsigned long)(arg8); \
988 _argvec[9] = (unsigned long)(arg9); \
989 _argvec[10] = (unsigned long)(arg10); \
990 __asm__ volatile( \
991 "pushl 40(%%eax)\n\t" \
992 "pushl 36(%%eax)\n\t" \
993 "pushl 32(%%eax)\n\t" \
994 "pushl 28(%%eax)\n\t" \
995 "pushl 24(%%eax)\n\t" \
996 "pushl 20(%%eax)\n\t" \
997 "pushl 16(%%eax)\n\t" \
998 "pushl 12(%%eax)\n\t" \
999 "pushl 8(%%eax)\n\t" \
1000 "pushl 4(%%eax)\n\t" \
1001 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1002 VALGRIND_CALL_NOREDIR_EAX \
1003 "addl $40, %%esp\n" \
1004 : /*out*/ "=a" (_res) \
1005 : /*in*/ "a" (&_argvec[0]) \
1006 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1007 ); \
1008 lval = (__typeof__(lval)) _res; \
1009 } while (0)
1010
sewardj5ce4b152006-03-11 12:57:41 +00001011#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1012 arg6,arg7,arg8,arg9,arg10, \
1013 arg11) \
1014 do { \
1015 volatile OrigFn _orig = (orig); \
1016 volatile unsigned long _argvec[12]; \
1017 volatile unsigned long _res; \
1018 _argvec[0] = (unsigned long)_orig.nraddr; \
1019 _argvec[1] = (unsigned long)(arg1); \
1020 _argvec[2] = (unsigned long)(arg2); \
1021 _argvec[3] = (unsigned long)(arg3); \
1022 _argvec[4] = (unsigned long)(arg4); \
1023 _argvec[5] = (unsigned long)(arg5); \
1024 _argvec[6] = (unsigned long)(arg6); \
1025 _argvec[7] = (unsigned long)(arg7); \
1026 _argvec[8] = (unsigned long)(arg8); \
1027 _argvec[9] = (unsigned long)(arg9); \
1028 _argvec[10] = (unsigned long)(arg10); \
1029 _argvec[11] = (unsigned long)(arg11); \
1030 __asm__ volatile( \
1031 "pushl 44(%%eax)\n\t" \
1032 "pushl 40(%%eax)\n\t" \
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 $44, %%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
sewardj66226cc2006-01-20 15:46:46 +00001052#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1053 arg6,arg7,arg8,arg9,arg10, \
1054 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +00001055 do { \
sewardj66226cc2006-01-20 15:46:46 +00001056 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001057 volatile unsigned long _argvec[13]; \
1058 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001059 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001060 _argvec[1] = (unsigned long)(arg1); \
1061 _argvec[2] = (unsigned long)(arg2); \
1062 _argvec[3] = (unsigned long)(arg3); \
1063 _argvec[4] = (unsigned long)(arg4); \
1064 _argvec[5] = (unsigned long)(arg5); \
1065 _argvec[6] = (unsigned long)(arg6); \
1066 _argvec[7] = (unsigned long)(arg7); \
1067 _argvec[8] = (unsigned long)(arg8); \
1068 _argvec[9] = (unsigned long)(arg9); \
1069 _argvec[10] = (unsigned long)(arg10); \
1070 _argvec[11] = (unsigned long)(arg11); \
1071 _argvec[12] = (unsigned long)(arg12); \
1072 __asm__ volatile( \
1073 "pushl 48(%%eax)\n\t" \
1074 "pushl 44(%%eax)\n\t" \
1075 "pushl 40(%%eax)\n\t" \
1076 "pushl 36(%%eax)\n\t" \
1077 "pushl 32(%%eax)\n\t" \
1078 "pushl 28(%%eax)\n\t" \
1079 "pushl 24(%%eax)\n\t" \
1080 "pushl 20(%%eax)\n\t" \
1081 "pushl 16(%%eax)\n\t" \
1082 "pushl 12(%%eax)\n\t" \
1083 "pushl 8(%%eax)\n\t" \
1084 "pushl 4(%%eax)\n\t" \
1085 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1086 VALGRIND_CALL_NOREDIR_EAX \
1087 "addl $48, %%esp\n" \
1088 : /*out*/ "=a" (_res) \
1089 : /*in*/ "a" (&_argvec[0]) \
1090 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1091 ); \
1092 lval = (__typeof__(lval)) _res; \
1093 } while (0)
1094
njnf76d27a2009-05-28 01:53:07 +00001095#endif /* PLAT_x86_linux || PLAT_x86_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001096
njnf76d27a2009-05-28 01:53:07 +00001097/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001098
njnf76d27a2009-05-28 01:53:07 +00001099#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardj0ec07f32006-01-12 12:32:32 +00001100
1101/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1102
1103/* These regs are trashed by the hidden call. */
1104#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1105 "rdi", "r8", "r9", "r10", "r11"
1106
1107/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1108 long) == 8. */
1109
sewardja07c2e12007-11-09 23:09:50 +00001110/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1111 macros. In order not to trash the stack redzone, we need to drop
1112 %rsp by 128 before the hidden call, and restore afterwards. The
1113 nastyness is that it is only by luck that the stack still appears
1114 to be unwindable during the hidden call - since then the behaviour
1115 of any routine using this macro does not match what the CFI data
1116 says. Sigh.
1117
1118 Why is this important? Imagine that a wrapper has a stack
1119 allocated local, and passes to the hidden call, a pointer to it.
1120 Because gcc does not know about the hidden call, it may allocate
1121 that local in the redzone. Unfortunately the hidden call may then
1122 trash it before it comes to use it. So we must step clear of the
1123 redzone, for the duration of the hidden call, to make it safe.
1124
1125 Probably the same problem afflicts the other redzone-style ABIs too
1126 (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
1127 self describing (none of this CFI nonsense) so at least messing
1128 with the stack pointer doesn't give a danger of non-unwindable
1129 stack. */
1130
sewardjc8858442006-01-20 15:17:20 +00001131#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001132 do { \
sewardjc8858442006-01-20 15:17:20 +00001133 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001134 volatile unsigned long _argvec[1]; \
1135 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001136 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001137 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001138 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001139 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1140 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001141 "addq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001142 : /*out*/ "=a" (_res) \
1143 : /*in*/ "a" (&_argvec[0]) \
1144 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1145 ); \
1146 lval = (__typeof__(lval)) _res; \
1147 } while (0)
1148
sewardjc8858442006-01-20 15:17:20 +00001149#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001150 do { \
sewardjc8858442006-01-20 15:17:20 +00001151 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001152 volatile unsigned long _argvec[2]; \
1153 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001154 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001155 _argvec[1] = (unsigned long)(arg1); \
1156 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001157 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001158 "movq 8(%%rax), %%rdi\n\t" \
1159 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1160 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001161 "addq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001162 : /*out*/ "=a" (_res) \
1163 : /*in*/ "a" (&_argvec[0]) \
1164 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1165 ); \
1166 lval = (__typeof__(lval)) _res; \
1167 } while (0)
1168
sewardjc8858442006-01-20 15:17:20 +00001169#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001170 do { \
sewardjc8858442006-01-20 15:17:20 +00001171 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001172 volatile unsigned long _argvec[3]; \
1173 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001174 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001175 _argvec[1] = (unsigned long)(arg1); \
1176 _argvec[2] = (unsigned long)(arg2); \
1177 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001178 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001179 "movq 16(%%rax), %%rsi\n\t" \
1180 "movq 8(%%rax), %%rdi\n\t" \
1181 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1182 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001183 "addq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001184 : /*out*/ "=a" (_res) \
1185 : /*in*/ "a" (&_argvec[0]) \
1186 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1187 ); \
1188 lval = (__typeof__(lval)) _res; \
1189 } while (0)
1190
sewardja50f9dc2006-03-11 16:19:14 +00001191#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1192 do { \
1193 volatile OrigFn _orig = (orig); \
1194 volatile unsigned long _argvec[4]; \
1195 volatile unsigned long _res; \
1196 _argvec[0] = (unsigned long)_orig.nraddr; \
1197 _argvec[1] = (unsigned long)(arg1); \
1198 _argvec[2] = (unsigned long)(arg2); \
1199 _argvec[3] = (unsigned long)(arg3); \
1200 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001201 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001202 "movq 24(%%rax), %%rdx\n\t" \
1203 "movq 16(%%rax), %%rsi\n\t" \
1204 "movq 8(%%rax), %%rdi\n\t" \
1205 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1206 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001207 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001208 : /*out*/ "=a" (_res) \
1209 : /*in*/ "a" (&_argvec[0]) \
1210 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1211 ); \
1212 lval = (__typeof__(lval)) _res; \
1213 } while (0)
1214
1215#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1216 do { \
1217 volatile OrigFn _orig = (orig); \
1218 volatile unsigned long _argvec[5]; \
1219 volatile unsigned long _res; \
1220 _argvec[0] = (unsigned long)_orig.nraddr; \
1221 _argvec[1] = (unsigned long)(arg1); \
1222 _argvec[2] = (unsigned long)(arg2); \
1223 _argvec[3] = (unsigned long)(arg3); \
1224 _argvec[4] = (unsigned long)(arg4); \
1225 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001226 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001227 "movq 32(%%rax), %%rcx\n\t" \
1228 "movq 24(%%rax), %%rdx\n\t" \
1229 "movq 16(%%rax), %%rsi\n\t" \
1230 "movq 8(%%rax), %%rdi\n\t" \
1231 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1232 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001233 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001234 : /*out*/ "=a" (_res) \
1235 : /*in*/ "a" (&_argvec[0]) \
1236 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1237 ); \
1238 lval = (__typeof__(lval)) _res; \
1239 } while (0)
1240
1241#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1242 do { \
1243 volatile OrigFn _orig = (orig); \
1244 volatile unsigned long _argvec[6]; \
1245 volatile unsigned long _res; \
1246 _argvec[0] = (unsigned long)_orig.nraddr; \
1247 _argvec[1] = (unsigned long)(arg1); \
1248 _argvec[2] = (unsigned long)(arg2); \
1249 _argvec[3] = (unsigned long)(arg3); \
1250 _argvec[4] = (unsigned long)(arg4); \
1251 _argvec[5] = (unsigned long)(arg5); \
1252 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001253 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001254 "movq 40(%%rax), %%r8\n\t" \
1255 "movq 32(%%rax), %%rcx\n\t" \
1256 "movq 24(%%rax), %%rdx\n\t" \
1257 "movq 16(%%rax), %%rsi\n\t" \
1258 "movq 8(%%rax), %%rdi\n\t" \
1259 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1260 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001261 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001262 : /*out*/ "=a" (_res) \
1263 : /*in*/ "a" (&_argvec[0]) \
1264 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1265 ); \
1266 lval = (__typeof__(lval)) _res; \
1267 } while (0)
1268
1269#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1270 do { \
1271 volatile OrigFn _orig = (orig); \
1272 volatile unsigned long _argvec[7]; \
1273 volatile unsigned long _res; \
1274 _argvec[0] = (unsigned long)_orig.nraddr; \
1275 _argvec[1] = (unsigned long)(arg1); \
1276 _argvec[2] = (unsigned long)(arg2); \
1277 _argvec[3] = (unsigned long)(arg3); \
1278 _argvec[4] = (unsigned long)(arg4); \
1279 _argvec[5] = (unsigned long)(arg5); \
1280 _argvec[6] = (unsigned long)(arg6); \
1281 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001282 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001283 "movq 48(%%rax), %%r9\n\t" \
1284 "movq 40(%%rax), %%r8\n\t" \
1285 "movq 32(%%rax), %%rcx\n\t" \
1286 "movq 24(%%rax), %%rdx\n\t" \
1287 "movq 16(%%rax), %%rsi\n\t" \
1288 "movq 8(%%rax), %%rdi\n\t" \
1289 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
sewardja07c2e12007-11-09 23:09:50 +00001290 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001291 VALGRIND_CALL_NOREDIR_RAX \
1292 : /*out*/ "=a" (_res) \
1293 : /*in*/ "a" (&_argvec[0]) \
1294 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1295 ); \
1296 lval = (__typeof__(lval)) _res; \
1297 } while (0)
1298
1299#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1300 arg7) \
1301 do { \
1302 volatile OrigFn _orig = (orig); \
1303 volatile unsigned long _argvec[8]; \
1304 volatile unsigned long _res; \
1305 _argvec[0] = (unsigned long)_orig.nraddr; \
1306 _argvec[1] = (unsigned long)(arg1); \
1307 _argvec[2] = (unsigned long)(arg2); \
1308 _argvec[3] = (unsigned long)(arg3); \
1309 _argvec[4] = (unsigned long)(arg4); \
1310 _argvec[5] = (unsigned long)(arg5); \
1311 _argvec[6] = (unsigned long)(arg6); \
1312 _argvec[7] = (unsigned long)(arg7); \
1313 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001314 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001315 "pushq 56(%%rax)\n\t" \
1316 "movq 48(%%rax), %%r9\n\t" \
1317 "movq 40(%%rax), %%r8\n\t" \
1318 "movq 32(%%rax), %%rcx\n\t" \
1319 "movq 24(%%rax), %%rdx\n\t" \
1320 "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 \
1324 "addq $8, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001325 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001326 : /*out*/ "=a" (_res) \
1327 : /*in*/ "a" (&_argvec[0]) \
1328 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1329 ); \
1330 lval = (__typeof__(lval)) _res; \
1331 } while (0)
1332
1333#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1334 arg7,arg8) \
1335 do { \
1336 volatile OrigFn _orig = (orig); \
1337 volatile unsigned long _argvec[9]; \
1338 volatile unsigned long _res; \
1339 _argvec[0] = (unsigned long)_orig.nraddr; \
1340 _argvec[1] = (unsigned long)(arg1); \
1341 _argvec[2] = (unsigned long)(arg2); \
1342 _argvec[3] = (unsigned long)(arg3); \
1343 _argvec[4] = (unsigned long)(arg4); \
1344 _argvec[5] = (unsigned long)(arg5); \
1345 _argvec[6] = (unsigned long)(arg6); \
1346 _argvec[7] = (unsigned long)(arg7); \
1347 _argvec[8] = (unsigned long)(arg8); \
1348 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001349 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001350 "pushq 64(%%rax)\n\t" \
1351 "pushq 56(%%rax)\n\t" \
1352 "movq 48(%%rax), %%r9\n\t" \
1353 "movq 40(%%rax), %%r8\n\t" \
1354 "movq 32(%%rax), %%rcx\n\t" \
1355 "movq 24(%%rax), %%rdx\n\t" \
1356 "movq 16(%%rax), %%rsi\n\t" \
1357 "movq 8(%%rax), %%rdi\n\t" \
1358 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1359 VALGRIND_CALL_NOREDIR_RAX \
1360 "addq $16, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001361 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001362 : /*out*/ "=a" (_res) \
1363 : /*in*/ "a" (&_argvec[0]) \
1364 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1365 ); \
1366 lval = (__typeof__(lval)) _res; \
1367 } while (0)
1368
1369#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1370 arg7,arg8,arg9) \
1371 do { \
1372 volatile OrigFn _orig = (orig); \
1373 volatile unsigned long _argvec[10]; \
1374 volatile unsigned long _res; \
1375 _argvec[0] = (unsigned long)_orig.nraddr; \
1376 _argvec[1] = (unsigned long)(arg1); \
1377 _argvec[2] = (unsigned long)(arg2); \
1378 _argvec[3] = (unsigned long)(arg3); \
1379 _argvec[4] = (unsigned long)(arg4); \
1380 _argvec[5] = (unsigned long)(arg5); \
1381 _argvec[6] = (unsigned long)(arg6); \
1382 _argvec[7] = (unsigned long)(arg7); \
1383 _argvec[8] = (unsigned long)(arg8); \
1384 _argvec[9] = (unsigned long)(arg9); \
1385 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001386 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001387 "pushq 72(%%rax)\n\t" \
1388 "pushq 64(%%rax)\n\t" \
1389 "pushq 56(%%rax)\n\t" \
1390 "movq 48(%%rax), %%r9\n\t" \
1391 "movq 40(%%rax), %%r8\n\t" \
1392 "movq 32(%%rax), %%rcx\n\t" \
1393 "movq 24(%%rax), %%rdx\n\t" \
1394 "movq 16(%%rax), %%rsi\n\t" \
1395 "movq 8(%%rax), %%rdi\n\t" \
1396 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1397 VALGRIND_CALL_NOREDIR_RAX \
1398 "addq $24, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001399 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001400 : /*out*/ "=a" (_res) \
1401 : /*in*/ "a" (&_argvec[0]) \
1402 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1403 ); \
1404 lval = (__typeof__(lval)) _res; \
1405 } while (0)
1406
1407#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1408 arg7,arg8,arg9,arg10) \
1409 do { \
1410 volatile OrigFn _orig = (orig); \
1411 volatile unsigned long _argvec[11]; \
1412 volatile unsigned long _res; \
1413 _argvec[0] = (unsigned long)_orig.nraddr; \
1414 _argvec[1] = (unsigned long)(arg1); \
1415 _argvec[2] = (unsigned long)(arg2); \
1416 _argvec[3] = (unsigned long)(arg3); \
1417 _argvec[4] = (unsigned long)(arg4); \
1418 _argvec[5] = (unsigned long)(arg5); \
1419 _argvec[6] = (unsigned long)(arg6); \
1420 _argvec[7] = (unsigned long)(arg7); \
1421 _argvec[8] = (unsigned long)(arg8); \
1422 _argvec[9] = (unsigned long)(arg9); \
1423 _argvec[10] = (unsigned long)(arg10); \
1424 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001425 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001426 "pushq 80(%%rax)\n\t" \
1427 "pushq 72(%%rax)\n\t" \
1428 "pushq 64(%%rax)\n\t" \
1429 "pushq 56(%%rax)\n\t" \
1430 "movq 48(%%rax), %%r9\n\t" \
1431 "movq 40(%%rax), %%r8\n\t" \
1432 "movq 32(%%rax), %%rcx\n\t" \
1433 "movq 24(%%rax), %%rdx\n\t" \
1434 "movq 16(%%rax), %%rsi\n\t" \
1435 "movq 8(%%rax), %%rdi\n\t" \
1436 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1437 VALGRIND_CALL_NOREDIR_RAX \
1438 "addq $32, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001439 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001440 : /*out*/ "=a" (_res) \
1441 : /*in*/ "a" (&_argvec[0]) \
1442 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1443 ); \
1444 lval = (__typeof__(lval)) _res; \
1445 } while (0)
1446
1447#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1448 arg7,arg8,arg9,arg10,arg11) \
1449 do { \
1450 volatile OrigFn _orig = (orig); \
1451 volatile unsigned long _argvec[12]; \
1452 volatile unsigned long _res; \
1453 _argvec[0] = (unsigned long)_orig.nraddr; \
1454 _argvec[1] = (unsigned long)(arg1); \
1455 _argvec[2] = (unsigned long)(arg2); \
1456 _argvec[3] = (unsigned long)(arg3); \
1457 _argvec[4] = (unsigned long)(arg4); \
1458 _argvec[5] = (unsigned long)(arg5); \
1459 _argvec[6] = (unsigned long)(arg6); \
1460 _argvec[7] = (unsigned long)(arg7); \
1461 _argvec[8] = (unsigned long)(arg8); \
1462 _argvec[9] = (unsigned long)(arg9); \
1463 _argvec[10] = (unsigned long)(arg10); \
1464 _argvec[11] = (unsigned long)(arg11); \
1465 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001466 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001467 "pushq 88(%%rax)\n\t" \
1468 "pushq 80(%%rax)\n\t" \
1469 "pushq 72(%%rax)\n\t" \
1470 "pushq 64(%%rax)\n\t" \
1471 "pushq 56(%%rax)\n\t" \
1472 "movq 48(%%rax), %%r9\n\t" \
1473 "movq 40(%%rax), %%r8\n\t" \
1474 "movq 32(%%rax), %%rcx\n\t" \
1475 "movq 24(%%rax), %%rdx\n\t" \
1476 "movq 16(%%rax), %%rsi\n\t" \
1477 "movq 8(%%rax), %%rdi\n\t" \
1478 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1479 VALGRIND_CALL_NOREDIR_RAX \
1480 "addq $40, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001481 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001482 : /*out*/ "=a" (_res) \
1483 : /*in*/ "a" (&_argvec[0]) \
1484 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1485 ); \
1486 lval = (__typeof__(lval)) _res; \
1487 } while (0)
1488
1489#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1490 arg7,arg8,arg9,arg10,arg11,arg12) \
1491 do { \
1492 volatile OrigFn _orig = (orig); \
1493 volatile unsigned long _argvec[13]; \
1494 volatile unsigned long _res; \
1495 _argvec[0] = (unsigned long)_orig.nraddr; \
1496 _argvec[1] = (unsigned long)(arg1); \
1497 _argvec[2] = (unsigned long)(arg2); \
1498 _argvec[3] = (unsigned long)(arg3); \
1499 _argvec[4] = (unsigned long)(arg4); \
1500 _argvec[5] = (unsigned long)(arg5); \
1501 _argvec[6] = (unsigned long)(arg6); \
1502 _argvec[7] = (unsigned long)(arg7); \
1503 _argvec[8] = (unsigned long)(arg8); \
1504 _argvec[9] = (unsigned long)(arg9); \
1505 _argvec[10] = (unsigned long)(arg10); \
1506 _argvec[11] = (unsigned long)(arg11); \
1507 _argvec[12] = (unsigned long)(arg12); \
1508 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001509 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001510 "pushq 96(%%rax)\n\t" \
1511 "pushq 88(%%rax)\n\t" \
1512 "pushq 80(%%rax)\n\t" \
1513 "pushq 72(%%rax)\n\t" \
1514 "pushq 64(%%rax)\n\t" \
1515 "pushq 56(%%rax)\n\t" \
1516 "movq 48(%%rax), %%r9\n\t" \
1517 "movq 40(%%rax), %%r8\n\t" \
1518 "movq 32(%%rax), %%rcx\n\t" \
1519 "movq 24(%%rax), %%rdx\n\t" \
1520 "movq 16(%%rax), %%rsi\n\t" \
1521 "movq 8(%%rax), %%rdi\n\t" \
1522 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1523 VALGRIND_CALL_NOREDIR_RAX \
1524 "addq $48, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001525 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001526 : /*out*/ "=a" (_res) \
1527 : /*in*/ "a" (&_argvec[0]) \
1528 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1529 ); \
1530 lval = (__typeof__(lval)) _res; \
1531 } while (0)
1532
njnf76d27a2009-05-28 01:53:07 +00001533#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001534
sewardjf5c1a7f2006-10-17 01:32:48 +00001535/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00001536
sewardjf5c1a7f2006-10-17 01:32:48 +00001537#if defined(PLAT_ppc32_linux)
sewardj0ec07f32006-01-12 12:32:32 +00001538
sewardjead61df2006-03-12 13:39:15 +00001539/* This is useful for finding out about the on-stack stuff:
1540
1541 extern int f9 ( int,int,int,int,int,int,int,int,int );
1542 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1543 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1544 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1545
1546 int g9 ( void ) {
1547 return f9(11,22,33,44,55,66,77,88,99);
1548 }
1549 int g10 ( void ) {
1550 return f10(11,22,33,44,55,66,77,88,99,110);
1551 }
1552 int g11 ( void ) {
1553 return f11(11,22,33,44,55,66,77,88,99,110,121);
1554 }
1555 int g12 ( void ) {
1556 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1557 }
1558*/
1559
sewardj0ec07f32006-01-12 12:32:32 +00001560/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1561
1562/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00001563#define __CALLER_SAVED_REGS \
1564 "lr", "ctr", "xer", \
1565 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1566 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1567 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00001568
sewardjead61df2006-03-12 13:39:15 +00001569/* These CALL_FN_ macros assume that on ppc32-linux,
1570 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00001571
sewardj38de0992006-01-20 16:46:34 +00001572#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001573 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001574 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001575 volatile unsigned long _argvec[1]; \
1576 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001577 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001578 __asm__ volatile( \
1579 "mr 11,%1\n\t" \
1580 "lwz 11,0(11)\n\t" /* target->r11 */ \
1581 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1582 "mr %0,3" \
1583 : /*out*/ "=r" (_res) \
1584 : /*in*/ "r" (&_argvec[0]) \
1585 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1586 ); \
1587 lval = (__typeof__(lval)) _res; \
1588 } while (0)
1589
sewardj38de0992006-01-20 16:46:34 +00001590#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001591 do { \
sewardj38de0992006-01-20 16:46:34 +00001592 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001593 volatile unsigned long _argvec[2]; \
1594 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001595 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001596 _argvec[1] = (unsigned long)arg1; \
1597 __asm__ volatile( \
1598 "mr 11,%1\n\t" \
1599 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1600 "lwz 11,0(11)\n\t" /* target->r11 */ \
1601 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1602 "mr %0,3" \
1603 : /*out*/ "=r" (_res) \
1604 : /*in*/ "r" (&_argvec[0]) \
1605 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1606 ); \
1607 lval = (__typeof__(lval)) _res; \
1608 } while (0)
1609
sewardj38de0992006-01-20 16:46:34 +00001610#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001611 do { \
sewardj38de0992006-01-20 16:46:34 +00001612 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001613 volatile unsigned long _argvec[3]; \
1614 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001615 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001616 _argvec[1] = (unsigned long)arg1; \
1617 _argvec[2] = (unsigned long)arg2; \
1618 __asm__ volatile( \
1619 "mr 11,%1\n\t" \
1620 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1621 "lwz 4,8(11)\n\t" \
1622 "lwz 11,0(11)\n\t" /* target->r11 */ \
1623 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1624 "mr %0,3" \
1625 : /*out*/ "=r" (_res) \
1626 : /*in*/ "r" (&_argvec[0]) \
1627 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1628 ); \
1629 lval = (__typeof__(lval)) _res; \
1630 } while (0)
1631
sewardjead61df2006-03-12 13:39:15 +00001632#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1633 do { \
1634 volatile OrigFn _orig = (orig); \
1635 volatile unsigned long _argvec[4]; \
1636 volatile unsigned long _res; \
1637 _argvec[0] = (unsigned long)_orig.nraddr; \
1638 _argvec[1] = (unsigned long)arg1; \
1639 _argvec[2] = (unsigned long)arg2; \
1640 _argvec[3] = (unsigned long)arg3; \
1641 __asm__ volatile( \
1642 "mr 11,%1\n\t" \
1643 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1644 "lwz 4,8(11)\n\t" \
1645 "lwz 5,12(11)\n\t" \
1646 "lwz 11,0(11)\n\t" /* target->r11 */ \
1647 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1648 "mr %0,3" \
1649 : /*out*/ "=r" (_res) \
1650 : /*in*/ "r" (&_argvec[0]) \
1651 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1652 ); \
1653 lval = (__typeof__(lval)) _res; \
1654 } while (0)
1655
1656#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1657 do { \
1658 volatile OrigFn _orig = (orig); \
1659 volatile unsigned long _argvec[5]; \
1660 volatile unsigned long _res; \
1661 _argvec[0] = (unsigned long)_orig.nraddr; \
1662 _argvec[1] = (unsigned long)arg1; \
1663 _argvec[2] = (unsigned long)arg2; \
1664 _argvec[3] = (unsigned long)arg3; \
1665 _argvec[4] = (unsigned long)arg4; \
1666 __asm__ volatile( \
1667 "mr 11,%1\n\t" \
1668 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1669 "lwz 4,8(11)\n\t" \
1670 "lwz 5,12(11)\n\t" \
1671 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1672 "lwz 11,0(11)\n\t" /* target->r11 */ \
1673 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1674 "mr %0,3" \
1675 : /*out*/ "=r" (_res) \
1676 : /*in*/ "r" (&_argvec[0]) \
1677 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1678 ); \
1679 lval = (__typeof__(lval)) _res; \
1680 } while (0)
1681
1682#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1683 do { \
1684 volatile OrigFn _orig = (orig); \
1685 volatile unsigned long _argvec[6]; \
1686 volatile unsigned long _res; \
1687 _argvec[0] = (unsigned long)_orig.nraddr; \
1688 _argvec[1] = (unsigned long)arg1; \
1689 _argvec[2] = (unsigned long)arg2; \
1690 _argvec[3] = (unsigned long)arg3; \
1691 _argvec[4] = (unsigned long)arg4; \
1692 _argvec[5] = (unsigned long)arg5; \
1693 __asm__ volatile( \
1694 "mr 11,%1\n\t" \
1695 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1696 "lwz 4,8(11)\n\t" \
1697 "lwz 5,12(11)\n\t" \
1698 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1699 "lwz 7,20(11)\n\t" \
1700 "lwz 11,0(11)\n\t" /* target->r11 */ \
1701 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1702 "mr %0,3" \
1703 : /*out*/ "=r" (_res) \
1704 : /*in*/ "r" (&_argvec[0]) \
1705 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1706 ); \
1707 lval = (__typeof__(lval)) _res; \
1708 } while (0)
1709
1710#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1711 do { \
1712 volatile OrigFn _orig = (orig); \
1713 volatile unsigned long _argvec[7]; \
1714 volatile unsigned long _res; \
1715 _argvec[0] = (unsigned long)_orig.nraddr; \
1716 _argvec[1] = (unsigned long)arg1; \
1717 _argvec[2] = (unsigned long)arg2; \
1718 _argvec[3] = (unsigned long)arg3; \
1719 _argvec[4] = (unsigned long)arg4; \
1720 _argvec[5] = (unsigned long)arg5; \
1721 _argvec[6] = (unsigned long)arg6; \
1722 __asm__ volatile( \
1723 "mr 11,%1\n\t" \
1724 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1725 "lwz 4,8(11)\n\t" \
1726 "lwz 5,12(11)\n\t" \
1727 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1728 "lwz 7,20(11)\n\t" \
1729 "lwz 8,24(11)\n\t" \
1730 "lwz 11,0(11)\n\t" /* target->r11 */ \
1731 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1732 "mr %0,3" \
1733 : /*out*/ "=r" (_res) \
1734 : /*in*/ "r" (&_argvec[0]) \
1735 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1736 ); \
1737 lval = (__typeof__(lval)) _res; \
1738 } while (0)
1739
1740#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1741 arg7) \
1742 do { \
1743 volatile OrigFn _orig = (orig); \
1744 volatile unsigned long _argvec[8]; \
1745 volatile unsigned long _res; \
1746 _argvec[0] = (unsigned long)_orig.nraddr; \
1747 _argvec[1] = (unsigned long)arg1; \
1748 _argvec[2] = (unsigned long)arg2; \
1749 _argvec[3] = (unsigned long)arg3; \
1750 _argvec[4] = (unsigned long)arg4; \
1751 _argvec[5] = (unsigned long)arg5; \
1752 _argvec[6] = (unsigned long)arg6; \
1753 _argvec[7] = (unsigned long)arg7; \
1754 __asm__ volatile( \
1755 "mr 11,%1\n\t" \
1756 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1757 "lwz 4,8(11)\n\t" \
1758 "lwz 5,12(11)\n\t" \
1759 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1760 "lwz 7,20(11)\n\t" \
1761 "lwz 8,24(11)\n\t" \
1762 "lwz 9,28(11)\n\t" \
1763 "lwz 11,0(11)\n\t" /* target->r11 */ \
1764 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1765 "mr %0,3" \
1766 : /*out*/ "=r" (_res) \
1767 : /*in*/ "r" (&_argvec[0]) \
1768 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1769 ); \
1770 lval = (__typeof__(lval)) _res; \
1771 } while (0)
1772
1773#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1774 arg7,arg8) \
1775 do { \
1776 volatile OrigFn _orig = (orig); \
1777 volatile unsigned long _argvec[9]; \
1778 volatile unsigned long _res; \
1779 _argvec[0] = (unsigned long)_orig.nraddr; \
1780 _argvec[1] = (unsigned long)arg1; \
1781 _argvec[2] = (unsigned long)arg2; \
1782 _argvec[3] = (unsigned long)arg3; \
1783 _argvec[4] = (unsigned long)arg4; \
1784 _argvec[5] = (unsigned long)arg5; \
1785 _argvec[6] = (unsigned long)arg6; \
1786 _argvec[7] = (unsigned long)arg7; \
1787 _argvec[8] = (unsigned long)arg8; \
1788 __asm__ volatile( \
1789 "mr 11,%1\n\t" \
1790 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1791 "lwz 4,8(11)\n\t" \
1792 "lwz 5,12(11)\n\t" \
1793 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1794 "lwz 7,20(11)\n\t" \
1795 "lwz 8,24(11)\n\t" \
1796 "lwz 9,28(11)\n\t" \
1797 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1798 "lwz 11,0(11)\n\t" /* target->r11 */ \
1799 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1800 "mr %0,3" \
1801 : /*out*/ "=r" (_res) \
1802 : /*in*/ "r" (&_argvec[0]) \
1803 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1804 ); \
1805 lval = (__typeof__(lval)) _res; \
1806 } while (0)
1807
1808#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1809 arg7,arg8,arg9) \
1810 do { \
1811 volatile OrigFn _orig = (orig); \
1812 volatile unsigned long _argvec[10]; \
1813 volatile unsigned long _res; \
1814 _argvec[0] = (unsigned long)_orig.nraddr; \
1815 _argvec[1] = (unsigned long)arg1; \
1816 _argvec[2] = (unsigned long)arg2; \
1817 _argvec[3] = (unsigned long)arg3; \
1818 _argvec[4] = (unsigned long)arg4; \
1819 _argvec[5] = (unsigned long)arg5; \
1820 _argvec[6] = (unsigned long)arg6; \
1821 _argvec[7] = (unsigned long)arg7; \
1822 _argvec[8] = (unsigned long)arg8; \
1823 _argvec[9] = (unsigned long)arg9; \
1824 __asm__ volatile( \
1825 "mr 11,%1\n\t" \
1826 "addi 1,1,-16\n\t" \
1827 /* arg9 */ \
1828 "lwz 3,36(11)\n\t" \
1829 "stw 3,8(1)\n\t" \
1830 /* args1-8 */ \
1831 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1832 "lwz 4,8(11)\n\t" \
1833 "lwz 5,12(11)\n\t" \
1834 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1835 "lwz 7,20(11)\n\t" \
1836 "lwz 8,24(11)\n\t" \
1837 "lwz 9,28(11)\n\t" \
1838 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1839 "lwz 11,0(11)\n\t" /* target->r11 */ \
1840 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1841 "addi 1,1,16\n\t" \
1842 "mr %0,3" \
1843 : /*out*/ "=r" (_res) \
1844 : /*in*/ "r" (&_argvec[0]) \
1845 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1846 ); \
1847 lval = (__typeof__(lval)) _res; \
1848 } while (0)
1849
1850#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1851 arg7,arg8,arg9,arg10) \
1852 do { \
1853 volatile OrigFn _orig = (orig); \
1854 volatile unsigned long _argvec[11]; \
1855 volatile unsigned long _res; \
1856 _argvec[0] = (unsigned long)_orig.nraddr; \
1857 _argvec[1] = (unsigned long)arg1; \
1858 _argvec[2] = (unsigned long)arg2; \
1859 _argvec[3] = (unsigned long)arg3; \
1860 _argvec[4] = (unsigned long)arg4; \
1861 _argvec[5] = (unsigned long)arg5; \
1862 _argvec[6] = (unsigned long)arg6; \
1863 _argvec[7] = (unsigned long)arg7; \
1864 _argvec[8] = (unsigned long)arg8; \
1865 _argvec[9] = (unsigned long)arg9; \
1866 _argvec[10] = (unsigned long)arg10; \
1867 __asm__ volatile( \
1868 "mr 11,%1\n\t" \
1869 "addi 1,1,-16\n\t" \
1870 /* arg10 */ \
1871 "lwz 3,40(11)\n\t" \
1872 "stw 3,12(1)\n\t" \
1873 /* arg9 */ \
1874 "lwz 3,36(11)\n\t" \
1875 "stw 3,8(1)\n\t" \
1876 /* args1-8 */ \
1877 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1878 "lwz 4,8(11)\n\t" \
1879 "lwz 5,12(11)\n\t" \
1880 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1881 "lwz 7,20(11)\n\t" \
1882 "lwz 8,24(11)\n\t" \
1883 "lwz 9,28(11)\n\t" \
1884 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1885 "lwz 11,0(11)\n\t" /* target->r11 */ \
1886 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1887 "addi 1,1,16\n\t" \
1888 "mr %0,3" \
1889 : /*out*/ "=r" (_res) \
1890 : /*in*/ "r" (&_argvec[0]) \
1891 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1892 ); \
1893 lval = (__typeof__(lval)) _res; \
1894 } while (0)
1895
1896#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1897 arg7,arg8,arg9,arg10,arg11) \
1898 do { \
1899 volatile OrigFn _orig = (orig); \
1900 volatile unsigned long _argvec[12]; \
1901 volatile unsigned long _res; \
1902 _argvec[0] = (unsigned long)_orig.nraddr; \
1903 _argvec[1] = (unsigned long)arg1; \
1904 _argvec[2] = (unsigned long)arg2; \
1905 _argvec[3] = (unsigned long)arg3; \
1906 _argvec[4] = (unsigned long)arg4; \
1907 _argvec[5] = (unsigned long)arg5; \
1908 _argvec[6] = (unsigned long)arg6; \
1909 _argvec[7] = (unsigned long)arg7; \
1910 _argvec[8] = (unsigned long)arg8; \
1911 _argvec[9] = (unsigned long)arg9; \
1912 _argvec[10] = (unsigned long)arg10; \
1913 _argvec[11] = (unsigned long)arg11; \
1914 __asm__ volatile( \
1915 "mr 11,%1\n\t" \
1916 "addi 1,1,-32\n\t" \
1917 /* arg11 */ \
1918 "lwz 3,44(11)\n\t" \
1919 "stw 3,16(1)\n\t" \
1920 /* arg10 */ \
1921 "lwz 3,40(11)\n\t" \
1922 "stw 3,12(1)\n\t" \
1923 /* arg9 */ \
1924 "lwz 3,36(11)\n\t" \
1925 "stw 3,8(1)\n\t" \
1926 /* args1-8 */ \
1927 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1928 "lwz 4,8(11)\n\t" \
1929 "lwz 5,12(11)\n\t" \
1930 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1931 "lwz 7,20(11)\n\t" \
1932 "lwz 8,24(11)\n\t" \
1933 "lwz 9,28(11)\n\t" \
1934 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1935 "lwz 11,0(11)\n\t" /* target->r11 */ \
1936 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1937 "addi 1,1,32\n\t" \
1938 "mr %0,3" \
1939 : /*out*/ "=r" (_res) \
1940 : /*in*/ "r" (&_argvec[0]) \
1941 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1942 ); \
1943 lval = (__typeof__(lval)) _res; \
1944 } while (0)
1945
1946#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1947 arg7,arg8,arg9,arg10,arg11,arg12) \
1948 do { \
1949 volatile OrigFn _orig = (orig); \
1950 volatile unsigned long _argvec[13]; \
1951 volatile unsigned long _res; \
1952 _argvec[0] = (unsigned long)_orig.nraddr; \
1953 _argvec[1] = (unsigned long)arg1; \
1954 _argvec[2] = (unsigned long)arg2; \
1955 _argvec[3] = (unsigned long)arg3; \
1956 _argvec[4] = (unsigned long)arg4; \
1957 _argvec[5] = (unsigned long)arg5; \
1958 _argvec[6] = (unsigned long)arg6; \
1959 _argvec[7] = (unsigned long)arg7; \
1960 _argvec[8] = (unsigned long)arg8; \
1961 _argvec[9] = (unsigned long)arg9; \
1962 _argvec[10] = (unsigned long)arg10; \
1963 _argvec[11] = (unsigned long)arg11; \
1964 _argvec[12] = (unsigned long)arg12; \
1965 __asm__ volatile( \
1966 "mr 11,%1\n\t" \
1967 "addi 1,1,-32\n\t" \
1968 /* arg12 */ \
1969 "lwz 3,48(11)\n\t" \
1970 "stw 3,20(1)\n\t" \
1971 /* arg11 */ \
1972 "lwz 3,44(11)\n\t" \
1973 "stw 3,16(1)\n\t" \
1974 /* arg10 */ \
1975 "lwz 3,40(11)\n\t" \
1976 "stw 3,12(1)\n\t" \
1977 /* arg9 */ \
1978 "lwz 3,36(11)\n\t" \
1979 "stw 3,8(1)\n\t" \
1980 /* args1-8 */ \
1981 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1982 "lwz 4,8(11)\n\t" \
1983 "lwz 5,12(11)\n\t" \
1984 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1985 "lwz 7,20(11)\n\t" \
1986 "lwz 8,24(11)\n\t" \
1987 "lwz 9,28(11)\n\t" \
1988 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1989 "lwz 11,0(11)\n\t" /* target->r11 */ \
1990 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1991 "addi 1,1,32\n\t" \
1992 "mr %0,3" \
1993 : /*out*/ "=r" (_res) \
1994 : /*in*/ "r" (&_argvec[0]) \
1995 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1996 ); \
1997 lval = (__typeof__(lval)) _res; \
1998 } while (0)
1999
sewardjf5c1a7f2006-10-17 01:32:48 +00002000#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +00002001
sewardjf5c1a7f2006-10-17 01:32:48 +00002002/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002003
sewardjf5c1a7f2006-10-17 01:32:48 +00002004#if defined(PLAT_ppc64_linux)
sewardj9734b202006-01-17 01:49:37 +00002005
2006/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2007
2008/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00002009#define __CALLER_SAVED_REGS \
2010 "lr", "ctr", "xer", \
2011 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2012 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2013 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00002014
2015/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2016 long) == 8. */
2017
sewardjd68ac3e2006-01-20 14:31:57 +00002018#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00002019 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002020 volatile OrigFn _orig = (orig); \
2021 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00002022 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002023 /* _argvec[0] holds current r2 across the call */ \
2024 _argvec[1] = (unsigned long)_orig.r2; \
2025 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00002026 __asm__ volatile( \
2027 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002028 "std 2,-16(11)\n\t" /* save tocptr */ \
2029 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2030 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002031 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2032 "mr 11,%1\n\t" \
2033 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002034 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002035 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002036 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002037 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2038 ); \
2039 lval = (__typeof__(lval)) _res; \
2040 } while (0)
2041
sewardjd68ac3e2006-01-20 14:31:57 +00002042#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00002043 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002044 volatile OrigFn _orig = (orig); \
2045 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00002046 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002047 /* _argvec[0] holds current r2 across the call */ \
2048 _argvec[1] = (unsigned long)_orig.r2; \
2049 _argvec[2] = (unsigned long)_orig.nraddr; \
2050 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00002051 __asm__ volatile( \
2052 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002053 "std 2,-16(11)\n\t" /* save tocptr */ \
2054 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2055 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2056 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002057 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2058 "mr 11,%1\n\t" \
2059 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002060 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002061 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002062 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002063 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2064 ); \
2065 lval = (__typeof__(lval)) _res; \
2066 } while (0)
2067
sewardjd68ac3e2006-01-20 14:31:57 +00002068#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00002069 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002070 volatile OrigFn _orig = (orig); \
2071 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00002072 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002073 /* _argvec[0] holds current r2 across the call */ \
2074 _argvec[1] = (unsigned long)_orig.r2; \
2075 _argvec[2] = (unsigned long)_orig.nraddr; \
2076 _argvec[2+1] = (unsigned long)arg1; \
2077 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00002078 __asm__ volatile( \
2079 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002080 "std 2,-16(11)\n\t" /* save tocptr */ \
2081 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2082 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00002083 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00002084 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002085 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2086 "mr 11,%1\n\t" \
2087 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002088 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002089 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002090 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002091 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2092 ); \
2093 lval = (__typeof__(lval)) _res; \
2094 } while (0)
2095
sewardjcd636392006-03-12 16:48:14 +00002096#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2097 do { \
2098 volatile OrigFn _orig = (orig); \
2099 volatile unsigned long _argvec[3+3]; \
2100 volatile unsigned long _res; \
2101 /* _argvec[0] holds current r2 across the call */ \
2102 _argvec[1] = (unsigned long)_orig.r2; \
2103 _argvec[2] = (unsigned long)_orig.nraddr; \
2104 _argvec[2+1] = (unsigned long)arg1; \
2105 _argvec[2+2] = (unsigned long)arg2; \
2106 _argvec[2+3] = (unsigned long)arg3; \
2107 __asm__ volatile( \
2108 "mr 11,%1\n\t" \
2109 "std 2,-16(11)\n\t" /* save tocptr */ \
2110 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2111 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2112 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2113 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2114 "ld 11, 0(11)\n\t" /* target->r11 */ \
2115 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2116 "mr 11,%1\n\t" \
2117 "mr %0,3\n\t" \
2118 "ld 2,-16(11)" /* restore tocptr */ \
2119 : /*out*/ "=r" (_res) \
2120 : /*in*/ "r" (&_argvec[2]) \
2121 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2122 ); \
2123 lval = (__typeof__(lval)) _res; \
2124 } while (0)
2125
2126#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2127 do { \
2128 volatile OrigFn _orig = (orig); \
2129 volatile unsigned long _argvec[3+4]; \
2130 volatile unsigned long _res; \
2131 /* _argvec[0] holds current r2 across the call */ \
2132 _argvec[1] = (unsigned long)_orig.r2; \
2133 _argvec[2] = (unsigned long)_orig.nraddr; \
2134 _argvec[2+1] = (unsigned long)arg1; \
2135 _argvec[2+2] = (unsigned long)arg2; \
2136 _argvec[2+3] = (unsigned long)arg3; \
2137 _argvec[2+4] = (unsigned long)arg4; \
2138 __asm__ volatile( \
2139 "mr 11,%1\n\t" \
2140 "std 2,-16(11)\n\t" /* save tocptr */ \
2141 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2142 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2143 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2144 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2145 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2146 "ld 11, 0(11)\n\t" /* target->r11 */ \
2147 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2148 "mr 11,%1\n\t" \
2149 "mr %0,3\n\t" \
2150 "ld 2,-16(11)" /* restore tocptr */ \
2151 : /*out*/ "=r" (_res) \
2152 : /*in*/ "r" (&_argvec[2]) \
2153 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2154 ); \
2155 lval = (__typeof__(lval)) _res; \
2156 } while (0)
2157
2158#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2159 do { \
2160 volatile OrigFn _orig = (orig); \
2161 volatile unsigned long _argvec[3+5]; \
2162 volatile unsigned long _res; \
2163 /* _argvec[0] holds current r2 across the call */ \
2164 _argvec[1] = (unsigned long)_orig.r2; \
2165 _argvec[2] = (unsigned long)_orig.nraddr; \
2166 _argvec[2+1] = (unsigned long)arg1; \
2167 _argvec[2+2] = (unsigned long)arg2; \
2168 _argvec[2+3] = (unsigned long)arg3; \
2169 _argvec[2+4] = (unsigned long)arg4; \
2170 _argvec[2+5] = (unsigned long)arg5; \
2171 __asm__ volatile( \
2172 "mr 11,%1\n\t" \
2173 "std 2,-16(11)\n\t" /* save tocptr */ \
2174 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2175 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2176 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2177 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2178 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2179 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2180 "ld 11, 0(11)\n\t" /* target->r11 */ \
2181 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2182 "mr 11,%1\n\t" \
2183 "mr %0,3\n\t" \
2184 "ld 2,-16(11)" /* restore tocptr */ \
2185 : /*out*/ "=r" (_res) \
2186 : /*in*/ "r" (&_argvec[2]) \
2187 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2188 ); \
2189 lval = (__typeof__(lval)) _res; \
2190 } while (0)
2191
2192#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2193 do { \
2194 volatile OrigFn _orig = (orig); \
2195 volatile unsigned long _argvec[3+6]; \
2196 volatile unsigned long _res; \
2197 /* _argvec[0] holds current r2 across the call */ \
2198 _argvec[1] = (unsigned long)_orig.r2; \
2199 _argvec[2] = (unsigned long)_orig.nraddr; \
2200 _argvec[2+1] = (unsigned long)arg1; \
2201 _argvec[2+2] = (unsigned long)arg2; \
2202 _argvec[2+3] = (unsigned long)arg3; \
2203 _argvec[2+4] = (unsigned long)arg4; \
2204 _argvec[2+5] = (unsigned long)arg5; \
2205 _argvec[2+6] = (unsigned long)arg6; \
2206 __asm__ volatile( \
2207 "mr 11,%1\n\t" \
2208 "std 2,-16(11)\n\t" /* save tocptr */ \
2209 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2210 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2211 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2212 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2213 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2214 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2215 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2216 "ld 11, 0(11)\n\t" /* target->r11 */ \
2217 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2218 "mr 11,%1\n\t" \
2219 "mr %0,3\n\t" \
2220 "ld 2,-16(11)" /* restore tocptr */ \
2221 : /*out*/ "=r" (_res) \
2222 : /*in*/ "r" (&_argvec[2]) \
2223 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2224 ); \
2225 lval = (__typeof__(lval)) _res; \
2226 } while (0)
2227
2228#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2229 arg7) \
2230 do { \
2231 volatile OrigFn _orig = (orig); \
2232 volatile unsigned long _argvec[3+7]; \
2233 volatile unsigned long _res; \
2234 /* _argvec[0] holds current r2 across the call */ \
2235 _argvec[1] = (unsigned long)_orig.r2; \
2236 _argvec[2] = (unsigned long)_orig.nraddr; \
2237 _argvec[2+1] = (unsigned long)arg1; \
2238 _argvec[2+2] = (unsigned long)arg2; \
2239 _argvec[2+3] = (unsigned long)arg3; \
2240 _argvec[2+4] = (unsigned long)arg4; \
2241 _argvec[2+5] = (unsigned long)arg5; \
2242 _argvec[2+6] = (unsigned long)arg6; \
2243 _argvec[2+7] = (unsigned long)arg7; \
2244 __asm__ volatile( \
2245 "mr 11,%1\n\t" \
2246 "std 2,-16(11)\n\t" /* save tocptr */ \
2247 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2248 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2249 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2250 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2251 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2252 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2253 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2254 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2255 "ld 11, 0(11)\n\t" /* target->r11 */ \
2256 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2257 "mr 11,%1\n\t" \
2258 "mr %0,3\n\t" \
2259 "ld 2,-16(11)" /* restore tocptr */ \
2260 : /*out*/ "=r" (_res) \
2261 : /*in*/ "r" (&_argvec[2]) \
2262 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2263 ); \
2264 lval = (__typeof__(lval)) _res; \
2265 } while (0)
2266
2267#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2268 arg7,arg8) \
2269 do { \
2270 volatile OrigFn _orig = (orig); \
2271 volatile unsigned long _argvec[3+8]; \
2272 volatile unsigned long _res; \
2273 /* _argvec[0] holds current r2 across the call */ \
2274 _argvec[1] = (unsigned long)_orig.r2; \
2275 _argvec[2] = (unsigned long)_orig.nraddr; \
2276 _argvec[2+1] = (unsigned long)arg1; \
2277 _argvec[2+2] = (unsigned long)arg2; \
2278 _argvec[2+3] = (unsigned long)arg3; \
2279 _argvec[2+4] = (unsigned long)arg4; \
2280 _argvec[2+5] = (unsigned long)arg5; \
2281 _argvec[2+6] = (unsigned long)arg6; \
2282 _argvec[2+7] = (unsigned long)arg7; \
2283 _argvec[2+8] = (unsigned long)arg8; \
2284 __asm__ volatile( \
2285 "mr 11,%1\n\t" \
2286 "std 2,-16(11)\n\t" /* save tocptr */ \
2287 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2288 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2289 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2290 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2291 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2292 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2293 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2294 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2295 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2296 "ld 11, 0(11)\n\t" /* target->r11 */ \
2297 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2298 "mr 11,%1\n\t" \
2299 "mr %0,3\n\t" \
2300 "ld 2,-16(11)" /* restore tocptr */ \
2301 : /*out*/ "=r" (_res) \
2302 : /*in*/ "r" (&_argvec[2]) \
2303 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2304 ); \
2305 lval = (__typeof__(lval)) _res; \
2306 } while (0)
2307
2308#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2309 arg7,arg8,arg9) \
2310 do { \
2311 volatile OrigFn _orig = (orig); \
2312 volatile unsigned long _argvec[3+9]; \
2313 volatile unsigned long _res; \
2314 /* _argvec[0] holds current r2 across the call */ \
2315 _argvec[1] = (unsigned long)_orig.r2; \
2316 _argvec[2] = (unsigned long)_orig.nraddr; \
2317 _argvec[2+1] = (unsigned long)arg1; \
2318 _argvec[2+2] = (unsigned long)arg2; \
2319 _argvec[2+3] = (unsigned long)arg3; \
2320 _argvec[2+4] = (unsigned long)arg4; \
2321 _argvec[2+5] = (unsigned long)arg5; \
2322 _argvec[2+6] = (unsigned long)arg6; \
2323 _argvec[2+7] = (unsigned long)arg7; \
2324 _argvec[2+8] = (unsigned long)arg8; \
2325 _argvec[2+9] = (unsigned long)arg9; \
2326 __asm__ volatile( \
2327 "mr 11,%1\n\t" \
2328 "std 2,-16(11)\n\t" /* save tocptr */ \
2329 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2330 "addi 1,1,-128\n\t" /* expand stack frame */ \
2331 /* arg9 */ \
2332 "ld 3,72(11)\n\t" \
2333 "std 3,112(1)\n\t" \
2334 /* args1-8 */ \
2335 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2336 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2337 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2338 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2339 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2340 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2341 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2342 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2343 "ld 11, 0(11)\n\t" /* target->r11 */ \
2344 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2345 "mr 11,%1\n\t" \
2346 "mr %0,3\n\t" \
2347 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2348 "addi 1,1,128" /* restore frame */ \
2349 : /*out*/ "=r" (_res) \
2350 : /*in*/ "r" (&_argvec[2]) \
2351 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2352 ); \
2353 lval = (__typeof__(lval)) _res; \
2354 } while (0)
2355
2356#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2357 arg7,arg8,arg9,arg10) \
2358 do { \
2359 volatile OrigFn _orig = (orig); \
2360 volatile unsigned long _argvec[3+10]; \
2361 volatile unsigned long _res; \
2362 /* _argvec[0] holds current r2 across the call */ \
2363 _argvec[1] = (unsigned long)_orig.r2; \
2364 _argvec[2] = (unsigned long)_orig.nraddr; \
2365 _argvec[2+1] = (unsigned long)arg1; \
2366 _argvec[2+2] = (unsigned long)arg2; \
2367 _argvec[2+3] = (unsigned long)arg3; \
2368 _argvec[2+4] = (unsigned long)arg4; \
2369 _argvec[2+5] = (unsigned long)arg5; \
2370 _argvec[2+6] = (unsigned long)arg6; \
2371 _argvec[2+7] = (unsigned long)arg7; \
2372 _argvec[2+8] = (unsigned long)arg8; \
2373 _argvec[2+9] = (unsigned long)arg9; \
2374 _argvec[2+10] = (unsigned long)arg10; \
2375 __asm__ volatile( \
2376 "mr 11,%1\n\t" \
2377 "std 2,-16(11)\n\t" /* save tocptr */ \
2378 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2379 "addi 1,1,-128\n\t" /* expand stack frame */ \
2380 /* arg10 */ \
2381 "ld 3,80(11)\n\t" \
2382 "std 3,120(1)\n\t" \
2383 /* arg9 */ \
2384 "ld 3,72(11)\n\t" \
2385 "std 3,112(1)\n\t" \
2386 /* args1-8 */ \
2387 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2388 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2389 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2390 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2391 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2392 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2393 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2394 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2395 "ld 11, 0(11)\n\t" /* target->r11 */ \
2396 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2397 "mr 11,%1\n\t" \
2398 "mr %0,3\n\t" \
2399 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2400 "addi 1,1,128" /* restore frame */ \
2401 : /*out*/ "=r" (_res) \
2402 : /*in*/ "r" (&_argvec[2]) \
2403 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2404 ); \
2405 lval = (__typeof__(lval)) _res; \
2406 } while (0)
2407
2408#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2409 arg7,arg8,arg9,arg10,arg11) \
2410 do { \
2411 volatile OrigFn _orig = (orig); \
2412 volatile unsigned long _argvec[3+11]; \
2413 volatile unsigned long _res; \
2414 /* _argvec[0] holds current r2 across the call */ \
2415 _argvec[1] = (unsigned long)_orig.r2; \
2416 _argvec[2] = (unsigned long)_orig.nraddr; \
2417 _argvec[2+1] = (unsigned long)arg1; \
2418 _argvec[2+2] = (unsigned long)arg2; \
2419 _argvec[2+3] = (unsigned long)arg3; \
2420 _argvec[2+4] = (unsigned long)arg4; \
2421 _argvec[2+5] = (unsigned long)arg5; \
2422 _argvec[2+6] = (unsigned long)arg6; \
2423 _argvec[2+7] = (unsigned long)arg7; \
2424 _argvec[2+8] = (unsigned long)arg8; \
2425 _argvec[2+9] = (unsigned long)arg9; \
2426 _argvec[2+10] = (unsigned long)arg10; \
2427 _argvec[2+11] = (unsigned long)arg11; \
2428 __asm__ volatile( \
2429 "mr 11,%1\n\t" \
2430 "std 2,-16(11)\n\t" /* save tocptr */ \
2431 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2432 "addi 1,1,-144\n\t" /* expand stack frame */ \
2433 /* arg11 */ \
2434 "ld 3,88(11)\n\t" \
2435 "std 3,128(1)\n\t" \
2436 /* arg10 */ \
2437 "ld 3,80(11)\n\t" \
2438 "std 3,120(1)\n\t" \
2439 /* arg9 */ \
2440 "ld 3,72(11)\n\t" \
2441 "std 3,112(1)\n\t" \
2442 /* args1-8 */ \
2443 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2444 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2445 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2446 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2447 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2448 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2449 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2450 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2451 "ld 11, 0(11)\n\t" /* target->r11 */ \
2452 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2453 "mr 11,%1\n\t" \
2454 "mr %0,3\n\t" \
2455 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2456 "addi 1,1,144" /* restore frame */ \
2457 : /*out*/ "=r" (_res) \
2458 : /*in*/ "r" (&_argvec[2]) \
2459 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2460 ); \
2461 lval = (__typeof__(lval)) _res; \
2462 } while (0)
2463
2464#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2465 arg7,arg8,arg9,arg10,arg11,arg12) \
2466 do { \
2467 volatile OrigFn _orig = (orig); \
2468 volatile unsigned long _argvec[3+12]; \
2469 volatile unsigned long _res; \
2470 /* _argvec[0] holds current r2 across the call */ \
2471 _argvec[1] = (unsigned long)_orig.r2; \
2472 _argvec[2] = (unsigned long)_orig.nraddr; \
2473 _argvec[2+1] = (unsigned long)arg1; \
2474 _argvec[2+2] = (unsigned long)arg2; \
2475 _argvec[2+3] = (unsigned long)arg3; \
2476 _argvec[2+4] = (unsigned long)arg4; \
2477 _argvec[2+5] = (unsigned long)arg5; \
2478 _argvec[2+6] = (unsigned long)arg6; \
2479 _argvec[2+7] = (unsigned long)arg7; \
2480 _argvec[2+8] = (unsigned long)arg8; \
2481 _argvec[2+9] = (unsigned long)arg9; \
2482 _argvec[2+10] = (unsigned long)arg10; \
2483 _argvec[2+11] = (unsigned long)arg11; \
2484 _argvec[2+12] = (unsigned long)arg12; \
2485 __asm__ volatile( \
2486 "mr 11,%1\n\t" \
2487 "std 2,-16(11)\n\t" /* save tocptr */ \
2488 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2489 "addi 1,1,-144\n\t" /* expand stack frame */ \
2490 /* arg12 */ \
2491 "ld 3,96(11)\n\t" \
2492 "std 3,136(1)\n\t" \
2493 /* arg11 */ \
2494 "ld 3,88(11)\n\t" \
2495 "std 3,128(1)\n\t" \
2496 /* arg10 */ \
2497 "ld 3,80(11)\n\t" \
2498 "std 3,120(1)\n\t" \
2499 /* arg9 */ \
2500 "ld 3,72(11)\n\t" \
2501 "std 3,112(1)\n\t" \
2502 /* args1-8 */ \
2503 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2504 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2505 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2506 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2507 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2508 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2509 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2510 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2511 "ld 11, 0(11)\n\t" /* target->r11 */ \
2512 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2513 "mr 11,%1\n\t" \
2514 "mr %0,3\n\t" \
2515 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2516 "addi 1,1,144" /* restore frame */ \
2517 : /*out*/ "=r" (_res) \
2518 : /*in*/ "r" (&_argvec[2]) \
2519 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2520 ); \
2521 lval = (__typeof__(lval)) _res; \
2522 } while (0)
2523
sewardjf5c1a7f2006-10-17 01:32:48 +00002524#endif /* PLAT_ppc64_linux */
2525
sewardj59570ff2010-01-01 11:59:33 +00002526/* ------------------------- arm-linux ------------------------- */
2527
2528#if defined(PLAT_arm_linux)
2529
2530/* These regs are trashed by the hidden call. */
2531#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
2532
2533/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
2534 long) == 4. */
2535
2536#define CALL_FN_W_v(lval, orig) \
2537 do { \
2538 volatile OrigFn _orig = (orig); \
2539 volatile unsigned long _argvec[1]; \
2540 volatile unsigned long _res; \
2541 _argvec[0] = (unsigned long)_orig.nraddr; \
2542 __asm__ volatile( \
2543 "ldr r4, [%1] \n\t" /* target->r4 */ \
2544 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2545 "mov %0, r0\n" \
2546 : /*out*/ "=r" (_res) \
2547 : /*in*/ "0" (&_argvec[0]) \
2548 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2549 ); \
2550 lval = (__typeof__(lval)) _res; \
2551 } while (0)
2552
2553#define CALL_FN_W_W(lval, orig, arg1) \
2554 do { \
2555 volatile OrigFn _orig = (orig); \
2556 volatile unsigned long _argvec[2]; \
2557 volatile unsigned long _res; \
2558 _argvec[0] = (unsigned long)_orig.nraddr; \
2559 _argvec[1] = (unsigned long)(arg1); \
2560 __asm__ volatile( \
2561 "ldr r0, [%1, #4] \n\t" \
2562 "ldr r4, [%1] \n\t" /* target->r4 */ \
2563 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2564 "mov %0, r0\n" \
2565 : /*out*/ "=r" (_res) \
2566 : /*in*/ "0" (&_argvec[0]) \
2567 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2568 ); \
2569 lval = (__typeof__(lval)) _res; \
2570 } while (0)
2571
2572#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2573 do { \
2574 volatile OrigFn _orig = (orig); \
2575 volatile unsigned long _argvec[3]; \
2576 volatile unsigned long _res; \
2577 _argvec[0] = (unsigned long)_orig.nraddr; \
2578 _argvec[1] = (unsigned long)(arg1); \
2579 _argvec[2] = (unsigned long)(arg2); \
2580 __asm__ volatile( \
2581 "ldr r0, [%1, #4] \n\t" \
2582 "ldr r1, [%1, #8] \n\t" \
2583 "ldr r4, [%1] \n\t" /* target->r4 */ \
2584 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2585 "mov %0, r0\n" \
2586 : /*out*/ "=r" (_res) \
2587 : /*in*/ "0" (&_argvec[0]) \
2588 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2589 ); \
2590 lval = (__typeof__(lval)) _res; \
2591 } while (0)
2592
2593#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2594 do { \
2595 volatile OrigFn _orig = (orig); \
2596 volatile unsigned long _argvec[4]; \
2597 volatile unsigned long _res; \
2598 _argvec[0] = (unsigned long)_orig.nraddr; \
2599 _argvec[1] = (unsigned long)(arg1); \
2600 _argvec[2] = (unsigned long)(arg2); \
2601 _argvec[3] = (unsigned long)(arg3); \
2602 __asm__ volatile( \
2603 "ldr r0, [%1, #4] \n\t" \
2604 "ldr r1, [%1, #8] \n\t" \
2605 "ldr r2, [%1, #12] \n\t" \
2606 "ldr r4, [%1] \n\t" /* target->r4 */ \
2607 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2608 "mov %0, r0\n" \
2609 : /*out*/ "=r" (_res) \
2610 : /*in*/ "0" (&_argvec[0]) \
2611 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2612 ); \
2613 lval = (__typeof__(lval)) _res; \
2614 } while (0)
2615
2616#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2617 do { \
2618 volatile OrigFn _orig = (orig); \
2619 volatile unsigned long _argvec[5]; \
2620 volatile unsigned long _res; \
2621 _argvec[0] = (unsigned long)_orig.nraddr; \
2622 _argvec[1] = (unsigned long)(arg1); \
2623 _argvec[2] = (unsigned long)(arg2); \
2624 _argvec[3] = (unsigned long)(arg3); \
2625 _argvec[4] = (unsigned long)(arg4); \
2626 __asm__ volatile( \
2627 "ldr r0, [%1, #4] \n\t" \
2628 "ldr r1, [%1, #8] \n\t" \
2629 "ldr r2, [%1, #12] \n\t" \
2630 "ldr r3, [%1, #16] \n\t" \
2631 "ldr r4, [%1] \n\t" /* target->r4 */ \
2632 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2633 "mov %0, r0" \
2634 : /*out*/ "=r" (_res) \
2635 : /*in*/ "0" (&_argvec[0]) \
2636 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2637 ); \
2638 lval = (__typeof__(lval)) _res; \
2639 } while (0)
2640
2641#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2642 do { \
2643 volatile OrigFn _orig = (orig); \
2644 volatile unsigned long _argvec[6]; \
2645 volatile unsigned long _res; \
2646 _argvec[0] = (unsigned long)_orig.nraddr; \
2647 _argvec[1] = (unsigned long)(arg1); \
2648 _argvec[2] = (unsigned long)(arg2); \
2649 _argvec[3] = (unsigned long)(arg3); \
2650 _argvec[4] = (unsigned long)(arg4); \
2651 _argvec[5] = (unsigned long)(arg5); \
2652 __asm__ volatile( \
2653 "ldr r0, [%1, #20] \n\t" \
2654 "push {r0} \n\t" \
2655 "ldr r0, [%1, #4] \n\t" \
2656 "ldr r1, [%1, #8] \n\t" \
2657 "ldr r2, [%1, #12] \n\t" \
2658 "ldr r3, [%1, #16] \n\t" \
2659 "ldr r4, [%1] \n\t" /* target->r4 */ \
2660 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2661 "add sp, sp, #4 \n\t" \
2662 "mov %0, r0" \
2663 : /*out*/ "=r" (_res) \
2664 : /*in*/ "0" (&_argvec[0]) \
2665 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2666 ); \
2667 lval = (__typeof__(lval)) _res; \
2668 } while (0)
2669
2670#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2671 do { \
2672 volatile OrigFn _orig = (orig); \
2673 volatile unsigned long _argvec[7]; \
2674 volatile unsigned long _res; \
2675 _argvec[0] = (unsigned long)_orig.nraddr; \
2676 _argvec[1] = (unsigned long)(arg1); \
2677 _argvec[2] = (unsigned long)(arg2); \
2678 _argvec[3] = (unsigned long)(arg3); \
2679 _argvec[4] = (unsigned long)(arg4); \
2680 _argvec[5] = (unsigned long)(arg5); \
2681 _argvec[6] = (unsigned long)(arg6); \
2682 __asm__ volatile( \
2683 "ldr r0, [%1, #20] \n\t" \
2684 "ldr r1, [%1, #24] \n\t" \
2685 "push {r0, r1} \n\t" \
2686 "ldr r0, [%1, #4] \n\t" \
2687 "ldr r1, [%1, #8] \n\t" \
2688 "ldr r2, [%1, #12] \n\t" \
2689 "ldr r3, [%1, #16] \n\t" \
2690 "ldr r4, [%1] \n\t" /* target->r4 */ \
2691 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2692 "add sp, sp, #8 \n\t" \
2693 "mov %0, r0" \
2694 : /*out*/ "=r" (_res) \
2695 : /*in*/ "0" (&_argvec[0]) \
2696 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2697 ); \
2698 lval = (__typeof__(lval)) _res; \
2699 } while (0)
2700
2701#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2702 arg7) \
2703 do { \
2704 volatile OrigFn _orig = (orig); \
2705 volatile unsigned long _argvec[8]; \
2706 volatile unsigned long _res; \
2707 _argvec[0] = (unsigned long)_orig.nraddr; \
2708 _argvec[1] = (unsigned long)(arg1); \
2709 _argvec[2] = (unsigned long)(arg2); \
2710 _argvec[3] = (unsigned long)(arg3); \
2711 _argvec[4] = (unsigned long)(arg4); \
2712 _argvec[5] = (unsigned long)(arg5); \
2713 _argvec[6] = (unsigned long)(arg6); \
2714 _argvec[7] = (unsigned long)(arg7); \
2715 __asm__ volatile( \
2716 "ldr r0, [%1, #20] \n\t" \
2717 "ldr r1, [%1, #24] \n\t" \
2718 "ldr r2, [%1, #28] \n\t" \
2719 "push {r0, r1, r2} \n\t" \
2720 "ldr r0, [%1, #4] \n\t" \
2721 "ldr r1, [%1, #8] \n\t" \
2722 "ldr r2, [%1, #12] \n\t" \
2723 "ldr r3, [%1, #16] \n\t" \
2724 "ldr r4, [%1] \n\t" /* target->r4 */ \
2725 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2726 "add sp, sp, #12 \n\t" \
2727 "mov %0, r0" \
2728 : /*out*/ "=r" (_res) \
2729 : /*in*/ "0" (&_argvec[0]) \
2730 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2731 ); \
2732 lval = (__typeof__(lval)) _res; \
2733 } while (0)
2734
2735#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2736 arg7,arg8) \
2737 do { \
2738 volatile OrigFn _orig = (orig); \
2739 volatile unsigned long _argvec[9]; \
2740 volatile unsigned long _res; \
2741 _argvec[0] = (unsigned long)_orig.nraddr; \
2742 _argvec[1] = (unsigned long)(arg1); \
2743 _argvec[2] = (unsigned long)(arg2); \
2744 _argvec[3] = (unsigned long)(arg3); \
2745 _argvec[4] = (unsigned long)(arg4); \
2746 _argvec[5] = (unsigned long)(arg5); \
2747 _argvec[6] = (unsigned long)(arg6); \
2748 _argvec[7] = (unsigned long)(arg7); \
2749 _argvec[8] = (unsigned long)(arg8); \
2750 __asm__ volatile( \
2751 "ldr r0, [%1, #20] \n\t" \
2752 "ldr r1, [%1, #24] \n\t" \
2753 "ldr r2, [%1, #28] \n\t" \
2754 "ldr r3, [%1, #32] \n\t" \
2755 "push {r0, r1, r2, r3} \n\t" \
2756 "ldr r0, [%1, #4] \n\t" \
2757 "ldr r1, [%1, #8] \n\t" \
2758 "ldr r2, [%1, #12] \n\t" \
2759 "ldr r3, [%1, #16] \n\t" \
2760 "ldr r4, [%1] \n\t" /* target->r4 */ \
2761 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2762 "add sp, sp, #16 \n\t" \
2763 "mov %0, r0" \
2764 : /*out*/ "=r" (_res) \
2765 : /*in*/ "0" (&_argvec[0]) \
2766 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2767 ); \
2768 lval = (__typeof__(lval)) _res; \
2769 } while (0)
2770
2771#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2772 arg7,arg8,arg9) \
2773 do { \
2774 volatile OrigFn _orig = (orig); \
2775 volatile unsigned long _argvec[10]; \
2776 volatile unsigned long _res; \
2777 _argvec[0] = (unsigned long)_orig.nraddr; \
2778 _argvec[1] = (unsigned long)(arg1); \
2779 _argvec[2] = (unsigned long)(arg2); \
2780 _argvec[3] = (unsigned long)(arg3); \
2781 _argvec[4] = (unsigned long)(arg4); \
2782 _argvec[5] = (unsigned long)(arg5); \
2783 _argvec[6] = (unsigned long)(arg6); \
2784 _argvec[7] = (unsigned long)(arg7); \
2785 _argvec[8] = (unsigned long)(arg8); \
2786 _argvec[9] = (unsigned long)(arg9); \
2787 __asm__ volatile( \
2788 "ldr r0, [%1, #20] \n\t" \
2789 "ldr r1, [%1, #24] \n\t" \
2790 "ldr r2, [%1, #28] \n\t" \
2791 "ldr r3, [%1, #32] \n\t" \
2792 "ldr r4, [%1, #36] \n\t" \
2793 "push {r0, r1, r2, r3, r4} \n\t" \
2794 "ldr r0, [%1, #4] \n\t" \
2795 "ldr r1, [%1, #8] \n\t" \
2796 "ldr r2, [%1, #12] \n\t" \
2797 "ldr r3, [%1, #16] \n\t" \
2798 "ldr r4, [%1] \n\t" /* target->r4 */ \
2799 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2800 "add sp, sp, #20 \n\t" \
2801 "mov %0, r0" \
2802 : /*out*/ "=r" (_res) \
2803 : /*in*/ "0" (&_argvec[0]) \
2804 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2805 ); \
2806 lval = (__typeof__(lval)) _res; \
2807 } while (0)
2808
2809#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2810 arg7,arg8,arg9,arg10) \
2811 do { \
2812 volatile OrigFn _orig = (orig); \
2813 volatile unsigned long _argvec[11]; \
2814 volatile unsigned long _res; \
2815 _argvec[0] = (unsigned long)_orig.nraddr; \
2816 _argvec[1] = (unsigned long)(arg1); \
2817 _argvec[2] = (unsigned long)(arg2); \
2818 _argvec[3] = (unsigned long)(arg3); \
2819 _argvec[4] = (unsigned long)(arg4); \
2820 _argvec[5] = (unsigned long)(arg5); \
2821 _argvec[6] = (unsigned long)(arg6); \
2822 _argvec[7] = (unsigned long)(arg7); \
2823 _argvec[8] = (unsigned long)(arg8); \
2824 _argvec[9] = (unsigned long)(arg9); \
2825 _argvec[10] = (unsigned long)(arg10); \
2826 __asm__ volatile( \
2827 "ldr r0, [%1, #40] \n\t" \
2828 "push {r0} \n\t" \
2829 "ldr r0, [%1, #20] \n\t" \
2830 "ldr r1, [%1, #24] \n\t" \
2831 "ldr r2, [%1, #28] \n\t" \
2832 "ldr r3, [%1, #32] \n\t" \
2833 "ldr r4, [%1, #36] \n\t" \
2834 "push {r0, r1, r2, r3, r4} \n\t" \
2835 "ldr r0, [%1, #4] \n\t" \
2836 "ldr r1, [%1, #8] \n\t" \
2837 "ldr r2, [%1, #12] \n\t" \
2838 "ldr r3, [%1, #16] \n\t" \
2839 "ldr r4, [%1] \n\t" /* target->r4 */ \
2840 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2841 "add sp, sp, #24 \n\t" \
2842 "mov %0, r0" \
2843 : /*out*/ "=r" (_res) \
2844 : /*in*/ "0" (&_argvec[0]) \
2845 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2846 ); \
2847 lval = (__typeof__(lval)) _res; \
2848 } while (0)
2849
2850#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
2851 arg6,arg7,arg8,arg9,arg10, \
2852 arg11) \
2853 do { \
2854 volatile OrigFn _orig = (orig); \
2855 volatile unsigned long _argvec[12]; \
2856 volatile unsigned long _res; \
2857 _argvec[0] = (unsigned long)_orig.nraddr; \
2858 _argvec[1] = (unsigned long)(arg1); \
2859 _argvec[2] = (unsigned long)(arg2); \
2860 _argvec[3] = (unsigned long)(arg3); \
2861 _argvec[4] = (unsigned long)(arg4); \
2862 _argvec[5] = (unsigned long)(arg5); \
2863 _argvec[6] = (unsigned long)(arg6); \
2864 _argvec[7] = (unsigned long)(arg7); \
2865 _argvec[8] = (unsigned long)(arg8); \
2866 _argvec[9] = (unsigned long)(arg9); \
2867 _argvec[10] = (unsigned long)(arg10); \
2868 _argvec[11] = (unsigned long)(arg11); \
2869 __asm__ volatile( \
2870 "ldr r0, [%1, #40] \n\t" \
2871 "ldr r1, [%1, #44] \n\t" \
2872 "push {r0, r1} \n\t" \
2873 "ldr r0, [%1, #20] \n\t" \
2874 "ldr r1, [%1, #24] \n\t" \
2875 "ldr r2, [%1, #28] \n\t" \
2876 "ldr r3, [%1, #32] \n\t" \
2877 "ldr r4, [%1, #36] \n\t" \
2878 "push {r0, r1, r2, r3, r4} \n\t" \
2879 "ldr r0, [%1, #4] \n\t" \
2880 "ldr r1, [%1, #8] \n\t" \
2881 "ldr r2, [%1, #12] \n\t" \
2882 "ldr r3, [%1, #16] \n\t" \
2883 "ldr r4, [%1] \n\t" /* target->r4 */ \
2884 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2885 "add sp, sp, #28 \n\t" \
2886 "mov %0, r0" \
2887 : /*out*/ "=r" (_res) \
2888 : /*in*/ "0" (&_argvec[0]) \
2889 : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \
2890 ); \
2891 lval = (__typeof__(lval)) _res; \
2892 } while (0)
2893
2894#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
2895 arg6,arg7,arg8,arg9,arg10, \
2896 arg11,arg12) \
2897 do { \
2898 volatile OrigFn _orig = (orig); \
2899 volatile unsigned long _argvec[13]; \
2900 volatile unsigned long _res; \
2901 _argvec[0] = (unsigned long)_orig.nraddr; \
2902 _argvec[1] = (unsigned long)(arg1); \
2903 _argvec[2] = (unsigned long)(arg2); \
2904 _argvec[3] = (unsigned long)(arg3); \
2905 _argvec[4] = (unsigned long)(arg4); \
2906 _argvec[5] = (unsigned long)(arg5); \
2907 _argvec[6] = (unsigned long)(arg6); \
2908 _argvec[7] = (unsigned long)(arg7); \
2909 _argvec[8] = (unsigned long)(arg8); \
2910 _argvec[9] = (unsigned long)(arg9); \
2911 _argvec[10] = (unsigned long)(arg10); \
2912 _argvec[11] = (unsigned long)(arg11); \
2913 _argvec[12] = (unsigned long)(arg12); \
2914 __asm__ volatile( \
2915 "ldr r0, [%1, #40] \n\t" \
2916 "ldr r1, [%1, #44] \n\t" \
2917 "ldr r2, [%1, #48] \n\t" \
2918 "push {r0, r1, r2} \n\t" \
2919 "ldr r0, [%1, #20] \n\t" \
2920 "ldr r1, [%1, #24] \n\t" \
2921 "ldr r2, [%1, #28] \n\t" \
2922 "ldr r3, [%1, #32] \n\t" \
2923 "ldr r4, [%1, #36] \n\t" \
2924 "push {r0, r1, r2, r3, r4} \n\t" \
2925 "ldr r0, [%1, #4] \n\t" \
2926 "ldr r1, [%1, #8] \n\t" \
2927 "ldr r2, [%1, #12] \n\t" \
2928 "ldr r3, [%1, #16] \n\t" \
2929 "ldr r4, [%1] \n\t" /* target->r4 */ \
2930 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2931 "add sp, sp, #32 \n\t" \
2932 "mov %0, r0" \
2933 : /*out*/ "=r" (_res) \
2934 : /*in*/ "0" (&_argvec[0]) \
2935 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2936 ); \
2937 lval = (__typeof__(lval)) _res; \
2938 } while (0)
2939
2940#endif /* PLAT_arm_linux */
2941
sewardjf5c1a7f2006-10-17 01:32:48 +00002942/* ------------------------ ppc32-aix5 ------------------------- */
2943
2944#if defined(PLAT_ppc32_aix5)
2945
2946/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2947
2948/* These regs are trashed by the hidden call. */
2949#define __CALLER_SAVED_REGS \
2950 "lr", "ctr", "xer", \
2951 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2952 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2953 "r11", "r12", "r13"
2954
2955/* Expand the stack frame, copying enough info that unwinding
2956 still works. Trashes r3. */
2957
2958#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
2959 "addi 1,1,-" #_n_fr "\n\t" \
2960 "lwz 3," #_n_fr "(1)\n\t" \
2961 "stw 3,0(1)\n\t"
2962
2963#define VG_CONTRACT_FRAME_BY(_n_fr) \
2964 "addi 1,1," #_n_fr "\n\t"
2965
2966/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
2967 long) == 4. */
2968
2969#define CALL_FN_W_v(lval, orig) \
2970 do { \
2971 volatile OrigFn _orig = (orig); \
2972 volatile unsigned long _argvec[3+0]; \
2973 volatile unsigned long _res; \
2974 /* _argvec[0] holds current r2 across the call */ \
2975 _argvec[1] = (unsigned long)_orig.r2; \
2976 _argvec[2] = (unsigned long)_orig.nraddr; \
2977 __asm__ volatile( \
2978 "mr 11,%1\n\t" \
2979 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2980 "stw 2,-8(11)\n\t" /* save tocptr */ \
2981 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2982 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2983 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2984 "mr 11,%1\n\t" \
2985 "mr %0,3\n\t" \
2986 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2987 VG_CONTRACT_FRAME_BY(512) \
2988 : /*out*/ "=r" (_res) \
2989 : /*in*/ "r" (&_argvec[2]) \
2990 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2991 ); \
2992 lval = (__typeof__(lval)) _res; \
2993 } while (0)
2994
2995#define CALL_FN_W_W(lval, orig, arg1) \
2996 do { \
2997 volatile OrigFn _orig = (orig); \
2998 volatile unsigned long _argvec[3+1]; \
2999 volatile unsigned long _res; \
3000 /* _argvec[0] holds current r2 across the call */ \
3001 _argvec[1] = (unsigned long)_orig.r2; \
3002 _argvec[2] = (unsigned long)_orig.nraddr; \
3003 _argvec[2+1] = (unsigned long)arg1; \
3004 __asm__ volatile( \
3005 "mr 11,%1\n\t" \
3006 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3007 "stw 2,-8(11)\n\t" /* save tocptr */ \
3008 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3009 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3010 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3011 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3012 "mr 11,%1\n\t" \
3013 "mr %0,3\n\t" \
3014 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3015 VG_CONTRACT_FRAME_BY(512) \
3016 : /*out*/ "=r" (_res) \
3017 : /*in*/ "r" (&_argvec[2]) \
3018 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3019 ); \
3020 lval = (__typeof__(lval)) _res; \
3021 } while (0)
3022
3023#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3024 do { \
3025 volatile OrigFn _orig = (orig); \
3026 volatile unsigned long _argvec[3+2]; \
3027 volatile unsigned long _res; \
3028 /* _argvec[0] holds current r2 across the call */ \
3029 _argvec[1] = (unsigned long)_orig.r2; \
3030 _argvec[2] = (unsigned long)_orig.nraddr; \
3031 _argvec[2+1] = (unsigned long)arg1; \
3032 _argvec[2+2] = (unsigned long)arg2; \
3033 __asm__ volatile( \
3034 "mr 11,%1\n\t" \
3035 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3036 "stw 2,-8(11)\n\t" /* save tocptr */ \
3037 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3038 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3039 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3040 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3041 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3042 "mr 11,%1\n\t" \
3043 "mr %0,3\n\t" \
3044 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3045 VG_CONTRACT_FRAME_BY(512) \
3046 : /*out*/ "=r" (_res) \
3047 : /*in*/ "r" (&_argvec[2]) \
3048 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3049 ); \
3050 lval = (__typeof__(lval)) _res; \
3051 } while (0)
3052
3053#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3054 do { \
3055 volatile OrigFn _orig = (orig); \
3056 volatile unsigned long _argvec[3+3]; \
3057 volatile unsigned long _res; \
3058 /* _argvec[0] holds current r2 across the call */ \
3059 _argvec[1] = (unsigned long)_orig.r2; \
3060 _argvec[2] = (unsigned long)_orig.nraddr; \
3061 _argvec[2+1] = (unsigned long)arg1; \
3062 _argvec[2+2] = (unsigned long)arg2; \
3063 _argvec[2+3] = (unsigned long)arg3; \
3064 __asm__ volatile( \
3065 "mr 11,%1\n\t" \
3066 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3067 "stw 2,-8(11)\n\t" /* save tocptr */ \
3068 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3069 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3070 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3071 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3072 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3073 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3074 "mr 11,%1\n\t" \
3075 "mr %0,3\n\t" \
3076 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3077 VG_CONTRACT_FRAME_BY(512) \
3078 : /*out*/ "=r" (_res) \
3079 : /*in*/ "r" (&_argvec[2]) \
3080 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3081 ); \
3082 lval = (__typeof__(lval)) _res; \
3083 } while (0)
3084
3085#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3086 do { \
3087 volatile OrigFn _orig = (orig); \
3088 volatile unsigned long _argvec[3+4]; \
3089 volatile unsigned long _res; \
3090 /* _argvec[0] holds current r2 across the call */ \
3091 _argvec[1] = (unsigned long)_orig.r2; \
3092 _argvec[2] = (unsigned long)_orig.nraddr; \
3093 _argvec[2+1] = (unsigned long)arg1; \
3094 _argvec[2+2] = (unsigned long)arg2; \
3095 _argvec[2+3] = (unsigned long)arg3; \
3096 _argvec[2+4] = (unsigned long)arg4; \
3097 __asm__ volatile( \
3098 "mr 11,%1\n\t" \
3099 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3100 "stw 2,-8(11)\n\t" /* save tocptr */ \
3101 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3102 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3103 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3104 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3105 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3106 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3107 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3108 "mr 11,%1\n\t" \
3109 "mr %0,3\n\t" \
3110 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3111 VG_CONTRACT_FRAME_BY(512) \
3112 : /*out*/ "=r" (_res) \
3113 : /*in*/ "r" (&_argvec[2]) \
3114 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3115 ); \
3116 lval = (__typeof__(lval)) _res; \
3117 } while (0)
3118
3119#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3120 do { \
3121 volatile OrigFn _orig = (orig); \
3122 volatile unsigned long _argvec[3+5]; \
3123 volatile unsigned long _res; \
3124 /* _argvec[0] holds current r2 across the call */ \
3125 _argvec[1] = (unsigned long)_orig.r2; \
3126 _argvec[2] = (unsigned long)_orig.nraddr; \
3127 _argvec[2+1] = (unsigned long)arg1; \
3128 _argvec[2+2] = (unsigned long)arg2; \
3129 _argvec[2+3] = (unsigned long)arg3; \
3130 _argvec[2+4] = (unsigned long)arg4; \
3131 _argvec[2+5] = (unsigned long)arg5; \
3132 __asm__ volatile( \
3133 "mr 11,%1\n\t" \
3134 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3135 "stw 2,-8(11)\n\t" /* save tocptr */ \
3136 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3137 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3138 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3139 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3140 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3141 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3142 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3143 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3144 "mr 11,%1\n\t" \
3145 "mr %0,3\n\t" \
3146 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3147 VG_CONTRACT_FRAME_BY(512) \
3148 : /*out*/ "=r" (_res) \
3149 : /*in*/ "r" (&_argvec[2]) \
3150 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3151 ); \
3152 lval = (__typeof__(lval)) _res; \
3153 } while (0)
3154
3155#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3156 do { \
3157 volatile OrigFn _orig = (orig); \
3158 volatile unsigned long _argvec[3+6]; \
3159 volatile unsigned long _res; \
3160 /* _argvec[0] holds current r2 across the call */ \
3161 _argvec[1] = (unsigned long)_orig.r2; \
3162 _argvec[2] = (unsigned long)_orig.nraddr; \
3163 _argvec[2+1] = (unsigned long)arg1; \
3164 _argvec[2+2] = (unsigned long)arg2; \
3165 _argvec[2+3] = (unsigned long)arg3; \
3166 _argvec[2+4] = (unsigned long)arg4; \
3167 _argvec[2+5] = (unsigned long)arg5; \
3168 _argvec[2+6] = (unsigned long)arg6; \
3169 __asm__ volatile( \
3170 "mr 11,%1\n\t" \
3171 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3172 "stw 2,-8(11)\n\t" /* save tocptr */ \
3173 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3174 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3175 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3176 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3177 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3178 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3179 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3180 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3181 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3182 "mr 11,%1\n\t" \
3183 "mr %0,3\n\t" \
3184 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3185 VG_CONTRACT_FRAME_BY(512) \
3186 : /*out*/ "=r" (_res) \
3187 : /*in*/ "r" (&_argvec[2]) \
3188 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3189 ); \
3190 lval = (__typeof__(lval)) _res; \
3191 } while (0)
3192
3193#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3194 arg7) \
3195 do { \
3196 volatile OrigFn _orig = (orig); \
3197 volatile unsigned long _argvec[3+7]; \
3198 volatile unsigned long _res; \
3199 /* _argvec[0] holds current r2 across the call */ \
3200 _argvec[1] = (unsigned long)_orig.r2; \
3201 _argvec[2] = (unsigned long)_orig.nraddr; \
3202 _argvec[2+1] = (unsigned long)arg1; \
3203 _argvec[2+2] = (unsigned long)arg2; \
3204 _argvec[2+3] = (unsigned long)arg3; \
3205 _argvec[2+4] = (unsigned long)arg4; \
3206 _argvec[2+5] = (unsigned long)arg5; \
3207 _argvec[2+6] = (unsigned long)arg6; \
3208 _argvec[2+7] = (unsigned long)arg7; \
3209 __asm__ volatile( \
3210 "mr 11,%1\n\t" \
3211 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3212 "stw 2,-8(11)\n\t" /* save tocptr */ \
3213 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3214 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3215 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3216 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3217 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3218 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3219 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3220 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3221 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3222 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3223 "mr 11,%1\n\t" \
3224 "mr %0,3\n\t" \
3225 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3226 VG_CONTRACT_FRAME_BY(512) \
3227 : /*out*/ "=r" (_res) \
3228 : /*in*/ "r" (&_argvec[2]) \
3229 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3230 ); \
3231 lval = (__typeof__(lval)) _res; \
3232 } while (0)
3233
3234#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3235 arg7,arg8) \
3236 do { \
3237 volatile OrigFn _orig = (orig); \
3238 volatile unsigned long _argvec[3+8]; \
3239 volatile unsigned long _res; \
3240 /* _argvec[0] holds current r2 across the call */ \
3241 _argvec[1] = (unsigned long)_orig.r2; \
3242 _argvec[2] = (unsigned long)_orig.nraddr; \
3243 _argvec[2+1] = (unsigned long)arg1; \
3244 _argvec[2+2] = (unsigned long)arg2; \
3245 _argvec[2+3] = (unsigned long)arg3; \
3246 _argvec[2+4] = (unsigned long)arg4; \
3247 _argvec[2+5] = (unsigned long)arg5; \
3248 _argvec[2+6] = (unsigned long)arg6; \
3249 _argvec[2+7] = (unsigned long)arg7; \
3250 _argvec[2+8] = (unsigned long)arg8; \
3251 __asm__ volatile( \
3252 "mr 11,%1\n\t" \
3253 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3254 "stw 2,-8(11)\n\t" /* save tocptr */ \
3255 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3256 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3257 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3258 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3259 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3260 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3261 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3262 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3263 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3264 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3265 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3266 "mr 11,%1\n\t" \
3267 "mr %0,3\n\t" \
3268 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3269 VG_CONTRACT_FRAME_BY(512) \
3270 : /*out*/ "=r" (_res) \
3271 : /*in*/ "r" (&_argvec[2]) \
3272 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3273 ); \
3274 lval = (__typeof__(lval)) _res; \
3275 } while (0)
3276
3277#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3278 arg7,arg8,arg9) \
3279 do { \
3280 volatile OrigFn _orig = (orig); \
3281 volatile unsigned long _argvec[3+9]; \
3282 volatile unsigned long _res; \
3283 /* _argvec[0] holds current r2 across the call */ \
3284 _argvec[1] = (unsigned long)_orig.r2; \
3285 _argvec[2] = (unsigned long)_orig.nraddr; \
3286 _argvec[2+1] = (unsigned long)arg1; \
3287 _argvec[2+2] = (unsigned long)arg2; \
3288 _argvec[2+3] = (unsigned long)arg3; \
3289 _argvec[2+4] = (unsigned long)arg4; \
3290 _argvec[2+5] = (unsigned long)arg5; \
3291 _argvec[2+6] = (unsigned long)arg6; \
3292 _argvec[2+7] = (unsigned long)arg7; \
3293 _argvec[2+8] = (unsigned long)arg8; \
3294 _argvec[2+9] = (unsigned long)arg9; \
3295 __asm__ volatile( \
3296 "mr 11,%1\n\t" \
3297 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3298 "stw 2,-8(11)\n\t" /* save tocptr */ \
3299 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3300 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3301 /* arg9 */ \
3302 "lwz 3,36(11)\n\t" \
3303 "stw 3,56(1)\n\t" \
3304 /* args1-8 */ \
3305 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3306 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3307 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3308 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3309 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3310 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3311 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3312 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3313 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3314 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3315 "mr 11,%1\n\t" \
3316 "mr %0,3\n\t" \
3317 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3318 VG_CONTRACT_FRAME_BY(64) \
3319 VG_CONTRACT_FRAME_BY(512) \
3320 : /*out*/ "=r" (_res) \
3321 : /*in*/ "r" (&_argvec[2]) \
3322 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3323 ); \
3324 lval = (__typeof__(lval)) _res; \
3325 } while (0)
3326
3327#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3328 arg7,arg8,arg9,arg10) \
3329 do { \
3330 volatile OrigFn _orig = (orig); \
3331 volatile unsigned long _argvec[3+10]; \
3332 volatile unsigned long _res; \
3333 /* _argvec[0] holds current r2 across the call */ \
3334 _argvec[1] = (unsigned long)_orig.r2; \
3335 _argvec[2] = (unsigned long)_orig.nraddr; \
3336 _argvec[2+1] = (unsigned long)arg1; \
3337 _argvec[2+2] = (unsigned long)arg2; \
3338 _argvec[2+3] = (unsigned long)arg3; \
3339 _argvec[2+4] = (unsigned long)arg4; \
3340 _argvec[2+5] = (unsigned long)arg5; \
3341 _argvec[2+6] = (unsigned long)arg6; \
3342 _argvec[2+7] = (unsigned long)arg7; \
3343 _argvec[2+8] = (unsigned long)arg8; \
3344 _argvec[2+9] = (unsigned long)arg9; \
3345 _argvec[2+10] = (unsigned long)arg10; \
3346 __asm__ volatile( \
3347 "mr 11,%1\n\t" \
3348 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3349 "stw 2,-8(11)\n\t" /* save tocptr */ \
3350 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3351 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3352 /* arg10 */ \
3353 "lwz 3,40(11)\n\t" \
3354 "stw 3,60(1)\n\t" \
3355 /* arg9 */ \
3356 "lwz 3,36(11)\n\t" \
3357 "stw 3,56(1)\n\t" \
3358 /* args1-8 */ \
3359 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3360 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3361 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3362 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3363 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3364 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3365 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3366 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3367 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3368 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3369 "mr 11,%1\n\t" \
3370 "mr %0,3\n\t" \
3371 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3372 VG_CONTRACT_FRAME_BY(64) \
3373 VG_CONTRACT_FRAME_BY(512) \
3374 : /*out*/ "=r" (_res) \
3375 : /*in*/ "r" (&_argvec[2]) \
3376 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3377 ); \
3378 lval = (__typeof__(lval)) _res; \
3379 } while (0)
3380
3381#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3382 arg7,arg8,arg9,arg10,arg11) \
3383 do { \
3384 volatile OrigFn _orig = (orig); \
3385 volatile unsigned long _argvec[3+11]; \
3386 volatile unsigned long _res; \
3387 /* _argvec[0] holds current r2 across the call */ \
3388 _argvec[1] = (unsigned long)_orig.r2; \
3389 _argvec[2] = (unsigned long)_orig.nraddr; \
3390 _argvec[2+1] = (unsigned long)arg1; \
3391 _argvec[2+2] = (unsigned long)arg2; \
3392 _argvec[2+3] = (unsigned long)arg3; \
3393 _argvec[2+4] = (unsigned long)arg4; \
3394 _argvec[2+5] = (unsigned long)arg5; \
3395 _argvec[2+6] = (unsigned long)arg6; \
3396 _argvec[2+7] = (unsigned long)arg7; \
3397 _argvec[2+8] = (unsigned long)arg8; \
3398 _argvec[2+9] = (unsigned long)arg9; \
3399 _argvec[2+10] = (unsigned long)arg10; \
3400 _argvec[2+11] = (unsigned long)arg11; \
3401 __asm__ volatile( \
3402 "mr 11,%1\n\t" \
3403 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3404 "stw 2,-8(11)\n\t" /* save tocptr */ \
3405 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3406 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3407 /* arg11 */ \
3408 "lwz 3,44(11)\n\t" \
3409 "stw 3,64(1)\n\t" \
3410 /* arg10 */ \
3411 "lwz 3,40(11)\n\t" \
3412 "stw 3,60(1)\n\t" \
3413 /* arg9 */ \
3414 "lwz 3,36(11)\n\t" \
3415 "stw 3,56(1)\n\t" \
3416 /* args1-8 */ \
3417 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3418 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3419 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3420 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3421 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3422 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3423 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3424 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3425 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3426 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3427 "mr 11,%1\n\t" \
3428 "mr %0,3\n\t" \
3429 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3430 VG_CONTRACT_FRAME_BY(72) \
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_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3440 arg7,arg8,arg9,arg10,arg11,arg12) \
3441 do { \
3442 volatile OrigFn _orig = (orig); \
3443 volatile unsigned long _argvec[3+12]; \
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 _argvec[2+10] = (unsigned long)arg10; \
3458 _argvec[2+11] = (unsigned long)arg11; \
3459 _argvec[2+12] = (unsigned long)arg12; \
3460 __asm__ volatile( \
3461 "mr 11,%1\n\t" \
3462 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3463 "stw 2,-8(11)\n\t" /* save tocptr */ \
3464 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3465 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3466 /* arg12 */ \
3467 "lwz 3,48(11)\n\t" \
3468 "stw 3,68(1)\n\t" \
3469 /* arg11 */ \
3470 "lwz 3,44(11)\n\t" \
3471 "stw 3,64(1)\n\t" \
3472 /* arg10 */ \
3473 "lwz 3,40(11)\n\t" \
3474 "stw 3,60(1)\n\t" \
3475 /* arg9 */ \
3476 "lwz 3,36(11)\n\t" \
3477 "stw 3,56(1)\n\t" \
3478 /* args1-8 */ \
3479 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3480 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3481 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3482 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3483 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3484 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3485 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3486 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3487 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3488 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3489 "mr 11,%1\n\t" \
3490 "mr %0,3\n\t" \
3491 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3492 VG_CONTRACT_FRAME_BY(72) \
3493 VG_CONTRACT_FRAME_BY(512) \
3494 : /*out*/ "=r" (_res) \
3495 : /*in*/ "r" (&_argvec[2]) \
3496 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3497 ); \
3498 lval = (__typeof__(lval)) _res; \
3499 } while (0)
3500
3501#endif /* PLAT_ppc32_aix5 */
3502
3503/* ------------------------ ppc64-aix5 ------------------------- */
3504
3505#if defined(PLAT_ppc64_aix5)
3506
3507/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3508
3509/* These regs are trashed by the hidden call. */
3510#define __CALLER_SAVED_REGS \
3511 "lr", "ctr", "xer", \
3512 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3513 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3514 "r11", "r12", "r13"
3515
3516/* Expand the stack frame, copying enough info that unwinding
3517 still works. Trashes r3. */
3518
3519#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3520 "addi 1,1,-" #_n_fr "\n\t" \
3521 "ld 3," #_n_fr "(1)\n\t" \
3522 "std 3,0(1)\n\t"
3523
3524#define VG_CONTRACT_FRAME_BY(_n_fr) \
3525 "addi 1,1," #_n_fr "\n\t"
3526
3527/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
3528 long) == 8. */
3529
3530#define CALL_FN_W_v(lval, orig) \
3531 do { \
3532 volatile OrigFn _orig = (orig); \
3533 volatile unsigned long _argvec[3+0]; \
3534 volatile unsigned long _res; \
3535 /* _argvec[0] holds current r2 across the call */ \
3536 _argvec[1] = (unsigned long)_orig.r2; \
3537 _argvec[2] = (unsigned long)_orig.nraddr; \
3538 __asm__ volatile( \
3539 "mr 11,%1\n\t" \
3540 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3541 "std 2,-16(11)\n\t" /* save tocptr */ \
3542 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3543 "ld 11, 0(11)\n\t" /* target->r11 */ \
3544 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3545 "mr 11,%1\n\t" \
3546 "mr %0,3\n\t" \
3547 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3548 VG_CONTRACT_FRAME_BY(512) \
3549 : /*out*/ "=r" (_res) \
3550 : /*in*/ "r" (&_argvec[2]) \
3551 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3552 ); \
3553 lval = (__typeof__(lval)) _res; \
3554 } while (0)
3555
3556#define CALL_FN_W_W(lval, orig, arg1) \
3557 do { \
3558 volatile OrigFn _orig = (orig); \
3559 volatile unsigned long _argvec[3+1]; \
3560 volatile unsigned long _res; \
3561 /* _argvec[0] holds current r2 across the call */ \
3562 _argvec[1] = (unsigned long)_orig.r2; \
3563 _argvec[2] = (unsigned long)_orig.nraddr; \
3564 _argvec[2+1] = (unsigned long)arg1; \
3565 __asm__ volatile( \
3566 "mr 11,%1\n\t" \
3567 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3568 "std 2,-16(11)\n\t" /* save tocptr */ \
3569 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3570 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3571 "ld 11, 0(11)\n\t" /* target->r11 */ \
3572 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3573 "mr 11,%1\n\t" \
3574 "mr %0,3\n\t" \
3575 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3576 VG_CONTRACT_FRAME_BY(512) \
3577 : /*out*/ "=r" (_res) \
3578 : /*in*/ "r" (&_argvec[2]) \
3579 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3580 ); \
3581 lval = (__typeof__(lval)) _res; \
3582 } while (0)
3583
3584#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3585 do { \
3586 volatile OrigFn _orig = (orig); \
3587 volatile unsigned long _argvec[3+2]; \
3588 volatile unsigned long _res; \
3589 /* _argvec[0] holds current r2 across the call */ \
3590 _argvec[1] = (unsigned long)_orig.r2; \
3591 _argvec[2] = (unsigned long)_orig.nraddr; \
3592 _argvec[2+1] = (unsigned long)arg1; \
3593 _argvec[2+2] = (unsigned long)arg2; \
3594 __asm__ volatile( \
3595 "mr 11,%1\n\t" \
3596 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3597 "std 2,-16(11)\n\t" /* save tocptr */ \
3598 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3599 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3600 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3601 "ld 11, 0(11)\n\t" /* target->r11 */ \
3602 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3603 "mr 11,%1\n\t" \
3604 "mr %0,3\n\t" \
3605 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3606 VG_CONTRACT_FRAME_BY(512) \
3607 : /*out*/ "=r" (_res) \
3608 : /*in*/ "r" (&_argvec[2]) \
3609 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3610 ); \
3611 lval = (__typeof__(lval)) _res; \
3612 } while (0)
3613
3614#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3615 do { \
3616 volatile OrigFn _orig = (orig); \
3617 volatile unsigned long _argvec[3+3]; \
3618 volatile unsigned long _res; \
3619 /* _argvec[0] holds current r2 across the call */ \
3620 _argvec[1] = (unsigned long)_orig.r2; \
3621 _argvec[2] = (unsigned long)_orig.nraddr; \
3622 _argvec[2+1] = (unsigned long)arg1; \
3623 _argvec[2+2] = (unsigned long)arg2; \
3624 _argvec[2+3] = (unsigned long)arg3; \
3625 __asm__ volatile( \
3626 "mr 11,%1\n\t" \
3627 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3628 "std 2,-16(11)\n\t" /* save tocptr */ \
3629 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3630 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3631 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3632 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3633 "ld 11, 0(11)\n\t" /* target->r11 */ \
3634 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3635 "mr 11,%1\n\t" \
3636 "mr %0,3\n\t" \
3637 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3638 VG_CONTRACT_FRAME_BY(512) \
3639 : /*out*/ "=r" (_res) \
3640 : /*in*/ "r" (&_argvec[2]) \
3641 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3642 ); \
3643 lval = (__typeof__(lval)) _res; \
3644 } while (0)
3645
3646#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3647 do { \
3648 volatile OrigFn _orig = (orig); \
3649 volatile unsigned long _argvec[3+4]; \
3650 volatile unsigned long _res; \
3651 /* _argvec[0] holds current r2 across the call */ \
3652 _argvec[1] = (unsigned long)_orig.r2; \
3653 _argvec[2] = (unsigned long)_orig.nraddr; \
3654 _argvec[2+1] = (unsigned long)arg1; \
3655 _argvec[2+2] = (unsigned long)arg2; \
3656 _argvec[2+3] = (unsigned long)arg3; \
3657 _argvec[2+4] = (unsigned long)arg4; \
3658 __asm__ volatile( \
3659 "mr 11,%1\n\t" \
3660 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3661 "std 2,-16(11)\n\t" /* save tocptr */ \
3662 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3663 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3664 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3665 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3666 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3667 "ld 11, 0(11)\n\t" /* target->r11 */ \
3668 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3669 "mr 11,%1\n\t" \
3670 "mr %0,3\n\t" \
3671 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3672 VG_CONTRACT_FRAME_BY(512) \
3673 : /*out*/ "=r" (_res) \
3674 : /*in*/ "r" (&_argvec[2]) \
3675 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3676 ); \
3677 lval = (__typeof__(lval)) _res; \
3678 } while (0)
3679
3680#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3681 do { \
3682 volatile OrigFn _orig = (orig); \
3683 volatile unsigned long _argvec[3+5]; \
3684 volatile unsigned long _res; \
3685 /* _argvec[0] holds current r2 across the call */ \
3686 _argvec[1] = (unsigned long)_orig.r2; \
3687 _argvec[2] = (unsigned long)_orig.nraddr; \
3688 _argvec[2+1] = (unsigned long)arg1; \
3689 _argvec[2+2] = (unsigned long)arg2; \
3690 _argvec[2+3] = (unsigned long)arg3; \
3691 _argvec[2+4] = (unsigned long)arg4; \
3692 _argvec[2+5] = (unsigned long)arg5; \
3693 __asm__ volatile( \
3694 "mr 11,%1\n\t" \
3695 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3696 "std 2,-16(11)\n\t" /* save tocptr */ \
3697 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3698 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3699 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3700 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3701 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3702 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3703 "ld 11, 0(11)\n\t" /* target->r11 */ \
3704 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3705 "mr 11,%1\n\t" \
3706 "mr %0,3\n\t" \
3707 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3708 VG_CONTRACT_FRAME_BY(512) \
3709 : /*out*/ "=r" (_res) \
3710 : /*in*/ "r" (&_argvec[2]) \
3711 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3712 ); \
3713 lval = (__typeof__(lval)) _res; \
3714 } while (0)
3715
3716#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3717 do { \
3718 volatile OrigFn _orig = (orig); \
3719 volatile unsigned long _argvec[3+6]; \
3720 volatile unsigned long _res; \
3721 /* _argvec[0] holds current r2 across the call */ \
3722 _argvec[1] = (unsigned long)_orig.r2; \
3723 _argvec[2] = (unsigned long)_orig.nraddr; \
3724 _argvec[2+1] = (unsigned long)arg1; \
3725 _argvec[2+2] = (unsigned long)arg2; \
3726 _argvec[2+3] = (unsigned long)arg3; \
3727 _argvec[2+4] = (unsigned long)arg4; \
3728 _argvec[2+5] = (unsigned long)arg5; \
3729 _argvec[2+6] = (unsigned long)arg6; \
3730 __asm__ volatile( \
3731 "mr 11,%1\n\t" \
3732 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3733 "std 2,-16(11)\n\t" /* save tocptr */ \
3734 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3735 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3736 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3737 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3738 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3739 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3740 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3741 "ld 11, 0(11)\n\t" /* target->r11 */ \
3742 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3743 "mr 11,%1\n\t" \
3744 "mr %0,3\n\t" \
3745 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3746 VG_CONTRACT_FRAME_BY(512) \
3747 : /*out*/ "=r" (_res) \
3748 : /*in*/ "r" (&_argvec[2]) \
3749 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3750 ); \
3751 lval = (__typeof__(lval)) _res; \
3752 } while (0)
3753
3754#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3755 arg7) \
3756 do { \
3757 volatile OrigFn _orig = (orig); \
3758 volatile unsigned long _argvec[3+7]; \
3759 volatile unsigned long _res; \
3760 /* _argvec[0] holds current r2 across the call */ \
3761 _argvec[1] = (unsigned long)_orig.r2; \
3762 _argvec[2] = (unsigned long)_orig.nraddr; \
3763 _argvec[2+1] = (unsigned long)arg1; \
3764 _argvec[2+2] = (unsigned long)arg2; \
3765 _argvec[2+3] = (unsigned long)arg3; \
3766 _argvec[2+4] = (unsigned long)arg4; \
3767 _argvec[2+5] = (unsigned long)arg5; \
3768 _argvec[2+6] = (unsigned long)arg6; \
3769 _argvec[2+7] = (unsigned long)arg7; \
3770 __asm__ volatile( \
3771 "mr 11,%1\n\t" \
3772 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3773 "std 2,-16(11)\n\t" /* save tocptr */ \
3774 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3775 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3776 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3777 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3778 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3779 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3780 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3781 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3782 "ld 11, 0(11)\n\t" /* target->r11 */ \
3783 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3784 "mr 11,%1\n\t" \
3785 "mr %0,3\n\t" \
3786 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3787 VG_CONTRACT_FRAME_BY(512) \
3788 : /*out*/ "=r" (_res) \
3789 : /*in*/ "r" (&_argvec[2]) \
3790 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3791 ); \
3792 lval = (__typeof__(lval)) _res; \
3793 } while (0)
3794
3795#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3796 arg7,arg8) \
3797 do { \
3798 volatile OrigFn _orig = (orig); \
3799 volatile unsigned long _argvec[3+8]; \
3800 volatile unsigned long _res; \
3801 /* _argvec[0] holds current r2 across the call */ \
3802 _argvec[1] = (unsigned long)_orig.r2; \
3803 _argvec[2] = (unsigned long)_orig.nraddr; \
3804 _argvec[2+1] = (unsigned long)arg1; \
3805 _argvec[2+2] = (unsigned long)arg2; \
3806 _argvec[2+3] = (unsigned long)arg3; \
3807 _argvec[2+4] = (unsigned long)arg4; \
3808 _argvec[2+5] = (unsigned long)arg5; \
3809 _argvec[2+6] = (unsigned long)arg6; \
3810 _argvec[2+7] = (unsigned long)arg7; \
3811 _argvec[2+8] = (unsigned long)arg8; \
3812 __asm__ volatile( \
3813 "mr 11,%1\n\t" \
3814 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3815 "std 2,-16(11)\n\t" /* save tocptr */ \
3816 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3817 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3818 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3819 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3820 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3821 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3822 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3823 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3824 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3825 "ld 11, 0(11)\n\t" /* target->r11 */ \
3826 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3827 "mr 11,%1\n\t" \
3828 "mr %0,3\n\t" \
3829 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3830 VG_CONTRACT_FRAME_BY(512) \
3831 : /*out*/ "=r" (_res) \
3832 : /*in*/ "r" (&_argvec[2]) \
3833 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3834 ); \
3835 lval = (__typeof__(lval)) _res; \
3836 } while (0)
3837
3838#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3839 arg7,arg8,arg9) \
3840 do { \
3841 volatile OrigFn _orig = (orig); \
3842 volatile unsigned long _argvec[3+9]; \
3843 volatile unsigned long _res; \
3844 /* _argvec[0] holds current r2 across the call */ \
3845 _argvec[1] = (unsigned long)_orig.r2; \
3846 _argvec[2] = (unsigned long)_orig.nraddr; \
3847 _argvec[2+1] = (unsigned long)arg1; \
3848 _argvec[2+2] = (unsigned long)arg2; \
3849 _argvec[2+3] = (unsigned long)arg3; \
3850 _argvec[2+4] = (unsigned long)arg4; \
3851 _argvec[2+5] = (unsigned long)arg5; \
3852 _argvec[2+6] = (unsigned long)arg6; \
3853 _argvec[2+7] = (unsigned long)arg7; \
3854 _argvec[2+8] = (unsigned long)arg8; \
3855 _argvec[2+9] = (unsigned long)arg9; \
3856 __asm__ volatile( \
3857 "mr 11,%1\n\t" \
3858 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3859 "std 2,-16(11)\n\t" /* save tocptr */ \
3860 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3861 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3862 /* arg9 */ \
3863 "ld 3,72(11)\n\t" \
3864 "std 3,112(1)\n\t" \
3865 /* args1-8 */ \
3866 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3867 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3868 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3869 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3870 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3871 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3872 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3873 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3874 "ld 11, 0(11)\n\t" /* target->r11 */ \
3875 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3876 "mr 11,%1\n\t" \
3877 "mr %0,3\n\t" \
3878 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3879 VG_CONTRACT_FRAME_BY(128) \
3880 VG_CONTRACT_FRAME_BY(512) \
3881 : /*out*/ "=r" (_res) \
3882 : /*in*/ "r" (&_argvec[2]) \
3883 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3884 ); \
3885 lval = (__typeof__(lval)) _res; \
3886 } while (0)
3887
3888#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3889 arg7,arg8,arg9,arg10) \
3890 do { \
3891 volatile OrigFn _orig = (orig); \
3892 volatile unsigned long _argvec[3+10]; \
3893 volatile unsigned long _res; \
3894 /* _argvec[0] holds current r2 across the call */ \
3895 _argvec[1] = (unsigned long)_orig.r2; \
3896 _argvec[2] = (unsigned long)_orig.nraddr; \
3897 _argvec[2+1] = (unsigned long)arg1; \
3898 _argvec[2+2] = (unsigned long)arg2; \
3899 _argvec[2+3] = (unsigned long)arg3; \
3900 _argvec[2+4] = (unsigned long)arg4; \
3901 _argvec[2+5] = (unsigned long)arg5; \
3902 _argvec[2+6] = (unsigned long)arg6; \
3903 _argvec[2+7] = (unsigned long)arg7; \
3904 _argvec[2+8] = (unsigned long)arg8; \
3905 _argvec[2+9] = (unsigned long)arg9; \
3906 _argvec[2+10] = (unsigned long)arg10; \
3907 __asm__ volatile( \
3908 "mr 11,%1\n\t" \
3909 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3910 "std 2,-16(11)\n\t" /* save tocptr */ \
3911 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3912 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3913 /* arg10 */ \
3914 "ld 3,80(11)\n\t" \
3915 "std 3,120(1)\n\t" \
3916 /* arg9 */ \
3917 "ld 3,72(11)\n\t" \
3918 "std 3,112(1)\n\t" \
3919 /* args1-8 */ \
3920 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3921 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3922 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3923 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3924 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3925 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3926 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3927 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3928 "ld 11, 0(11)\n\t" /* target->r11 */ \
3929 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3930 "mr 11,%1\n\t" \
3931 "mr %0,3\n\t" \
3932 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3933 VG_CONTRACT_FRAME_BY(128) \
3934 VG_CONTRACT_FRAME_BY(512) \
3935 : /*out*/ "=r" (_res) \
3936 : /*in*/ "r" (&_argvec[2]) \
3937 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3938 ); \
3939 lval = (__typeof__(lval)) _res; \
3940 } while (0)
3941
3942#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3943 arg7,arg8,arg9,arg10,arg11) \
3944 do { \
3945 volatile OrigFn _orig = (orig); \
3946 volatile unsigned long _argvec[3+11]; \
3947 volatile unsigned long _res; \
3948 /* _argvec[0] holds current r2 across the call */ \
3949 _argvec[1] = (unsigned long)_orig.r2; \
3950 _argvec[2] = (unsigned long)_orig.nraddr; \
3951 _argvec[2+1] = (unsigned long)arg1; \
3952 _argvec[2+2] = (unsigned long)arg2; \
3953 _argvec[2+3] = (unsigned long)arg3; \
3954 _argvec[2+4] = (unsigned long)arg4; \
3955 _argvec[2+5] = (unsigned long)arg5; \
3956 _argvec[2+6] = (unsigned long)arg6; \
3957 _argvec[2+7] = (unsigned long)arg7; \
3958 _argvec[2+8] = (unsigned long)arg8; \
3959 _argvec[2+9] = (unsigned long)arg9; \
3960 _argvec[2+10] = (unsigned long)arg10; \
3961 _argvec[2+11] = (unsigned long)arg11; \
3962 __asm__ volatile( \
3963 "mr 11,%1\n\t" \
3964 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3965 "std 2,-16(11)\n\t" /* save tocptr */ \
3966 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3967 VG_EXPAND_FRAME_BY_trashes_r3(144) \
3968 /* arg11 */ \
3969 "ld 3,88(11)\n\t" \
3970 "std 3,128(1)\n\t" \
3971 /* arg10 */ \
3972 "ld 3,80(11)\n\t" \
3973 "std 3,120(1)\n\t" \
3974 /* arg9 */ \
3975 "ld 3,72(11)\n\t" \
3976 "std 3,112(1)\n\t" \
3977 /* args1-8 */ \
3978 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3979 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3980 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3981 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3982 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3983 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3984 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3985 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3986 "ld 11, 0(11)\n\t" /* target->r11 */ \
3987 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3988 "mr 11,%1\n\t" \
3989 "mr %0,3\n\t" \
3990 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3991 VG_CONTRACT_FRAME_BY(144) \
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_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4001 arg7,arg8,arg9,arg10,arg11,arg12) \
4002 do { \
4003 volatile OrigFn _orig = (orig); \
4004 volatile unsigned long _argvec[3+12]; \
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 _argvec[2+10] = (unsigned long)arg10; \
4019 _argvec[2+11] = (unsigned long)arg11; \
4020 _argvec[2+12] = (unsigned long)arg12; \
4021 __asm__ volatile( \
4022 "mr 11,%1\n\t" \
4023 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4024 "std 2,-16(11)\n\t" /* save tocptr */ \
4025 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4026 VG_EXPAND_FRAME_BY_trashes_r3(144) \
4027 /* arg12 */ \
4028 "ld 3,96(11)\n\t" \
4029 "std 3,136(1)\n\t" \
4030 /* arg11 */ \
4031 "ld 3,88(11)\n\t" \
4032 "std 3,128(1)\n\t" \
4033 /* arg10 */ \
4034 "ld 3,80(11)\n\t" \
4035 "std 3,120(1)\n\t" \
4036 /* arg9 */ \
4037 "ld 3,72(11)\n\t" \
4038 "std 3,112(1)\n\t" \
4039 /* args1-8 */ \
4040 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4041 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4042 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4043 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4044 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4045 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4046 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4047 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4048 "ld 11, 0(11)\n\t" /* target->r11 */ \
4049 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4050 "mr 11,%1\n\t" \
4051 "mr %0,3\n\t" \
4052 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4053 VG_CONTRACT_FRAME_BY(144) \
4054 VG_CONTRACT_FRAME_BY(512) \
4055 : /*out*/ "=r" (_res) \
4056 : /*in*/ "r" (&_argvec[2]) \
4057 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4058 ); \
4059 lval = (__typeof__(lval)) _res; \
4060 } while (0)
4061
4062#endif /* PLAT_ppc64_aix5 */
sewardj9734b202006-01-17 01:49:37 +00004063
sewardj0ec07f32006-01-12 12:32:32 +00004064
4065/* ------------------------------------------------------------------ */
4066/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
4067/* */
njn30d76c62005-06-18 15:07:39 +00004068/* ------------------------------------------------------------------ */
4069
sewardj2e93c502002-04-12 11:12:52 +00004070/* Some request codes. There are many more of these, but most are not
4071 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00004072 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00004073
sewardj0ec07f32006-01-12 12:32:32 +00004074 Core ones are in the range 0x00000000--0x0000ffff. The non-public
4075 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00004076*/
4077
sewardj0ec07f32006-01-12 12:32:32 +00004078/* These macros are used by tools -- they must be public, but don't
4079 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00004080#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00004081 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00004082#define VG_IS_TOOL_USERREQ(a, b, v) \
4083 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00004084
sewardj5ce4b152006-03-11 12:57:41 +00004085/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
4086 This enum comprises an ABI exported by Valgrind to programs
4087 which use client requests. DO NOT CHANGE THE ORDER OF THESE
4088 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00004089typedef
njn4c791212003-05-02 17:53:54 +00004090 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
4091 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00004092
sewardj0ec07f32006-01-12 12:32:32 +00004093 /* These allow any function to be called from the simulated
4094 CPU but run on the real CPU. Nb: the first arg passed to
4095 the function is always the ThreadId of the running
4096 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00004097 function, etc. */
njn4c791212003-05-02 17:53:54 +00004098 VG_USERREQ__CLIENT_CALL0 = 0x1101,
4099 VG_USERREQ__CLIENT_CALL1 = 0x1102,
4100 VG_USERREQ__CLIENT_CALL2 = 0x1103,
4101 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00004102
sewardj0ec07f32006-01-12 12:32:32 +00004103 /* Can be useful in regression testing suites -- eg. can
4104 send Valgrind's output to /dev/null and still count
4105 errors. */
njn4c791212003-05-02 17:53:54 +00004106 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00004107
sewardj0ec07f32006-01-12 12:32:32 +00004108 /* These are useful and can be interpreted by any tool that
4109 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00004110 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
4111 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00004112 /* Memory pool support. */
4113 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
4114 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
4115 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
4116 VG_USERREQ__MEMPOOL_FREE = 0x1306,
sewardj2c1c9df2006-07-28 00:06:37 +00004117 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
sewardjc740d762006-10-05 17:59:23 +00004118 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
4119 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
4120 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
njnd7994182003-10-02 13:44:04 +00004121
fitzhardinge39de4b42003-10-31 07:12:21 +00004122 /* Allow printfs to valgrind log. */
njn30d76c62005-06-18 15:07:39 +00004123 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00004124 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
4125
4126 /* Stack support. */
4127 VG_USERREQ__STACK_REGISTER = 0x1501,
4128 VG_USERREQ__STACK_DEREGISTER = 0x1502,
sewardjc8259b82009-04-22 22:42:10 +00004129 VG_USERREQ__STACK_CHANGE = 0x1503,
4130
4131 /* Wine support */
4132 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601
njn25e49d8e72002-09-23 09:36:25 +00004133 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00004134
sewardj0ec07f32006-01-12 12:32:32 +00004135#if !defined(__GNUC__)
4136# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00004137#endif
sewardj2e93c502002-04-12 11:12:52 +00004138
sewardj0ec07f32006-01-12 12:32:32 +00004139/* Returns the number of Valgrinds this code is running under. That
4140 is, 0 if running natively, 1 if running under Valgrind, 2 if
4141 running under Valgrind which is running under another Valgrind,
4142 etc. */
4143#define RUNNING_ON_VALGRIND __extension__ \
4144 ({unsigned int _qzz_res; \
4145 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \
4146 VG_USERREQ__RUNNING_ON_VALGRIND, \
sewardj9af10a12006-02-01 14:59:42 +00004147 0, 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004148 _qzz_res; \
sewardjde4a1d02002-03-22 01:27:54 +00004149 })
4150
4151
sewardj18d75132002-05-16 11:06:21 +00004152/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
4153 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
4154 since it provides a way to make sure valgrind will retranslate the
4155 invalidated area. Returns no value. */
sewardj0ec07f32006-01-12 12:32:32 +00004156#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
4157 {unsigned int _qzz_res; \
4158 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4159 VG_USERREQ__DISCARD_TRANSLATIONS, \
sewardj9af10a12006-02-01 14:59:42 +00004160 _qzz_addr, _qzz_len, 0, 0, 0); \
sewardj18d75132002-05-16 11:06:21 +00004161 }
4162
njn26aba4d2005-05-16 13:31:23 +00004163
sewardj0ec07f32006-01-12 12:32:32 +00004164/* These requests are for getting Valgrind itself to print something.
njnd55f0d92009-08-03 01:38:56 +00004165 Possibly with a backtrace. This is a really ugly hack. The return value
4166 is the number of characters printed, excluding the "**<pid>** " part at the
4167 start and the backtrace (if present). */
sewardj0ec07f32006-01-12 12:32:32 +00004168
4169#if defined(NVALGRIND)
4170
4171# define VALGRIND_PRINTF(...)
4172# define VALGRIND_PRINTF_BACKTRACE(...)
njn26aba4d2005-05-16 13:31:23 +00004173
4174#else /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00004175
sewardj7eca0cc2006-04-12 17:15:35 +00004176/* Modern GCC will optimize the static routine out if unused,
4177 and unused attribute will shut down warnings about it. */
4178static int VALGRIND_PRINTF(const char *format, ...)
4179 __attribute__((format(__printf__, 1, 2), __unused__));
4180static int
fitzhardingea09a1b52003-11-07 23:09:48 +00004181VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00004182{
njnc6168192004-11-29 13:54:10 +00004183 unsigned long _qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00004184 va_list vargs;
4185 va_start(vargs, format);
sewardj0ec07f32006-01-12 12:32:32 +00004186 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF,
sewardj9af10a12006-02-01 14:59:42 +00004187 (unsigned long)format, (unsigned long)vargs,
4188 0, 0, 0);
fitzhardinge39de4b42003-10-31 07:12:21 +00004189 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00004190 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00004191}
4192
sewardj7eca0cc2006-04-12 17:15:35 +00004193static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
4194 __attribute__((format(__printf__, 1, 2), __unused__));
4195static int
fitzhardingea09a1b52003-11-07 23:09:48 +00004196VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00004197{
njnc6168192004-11-29 13:54:10 +00004198 unsigned long _qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00004199 va_list vargs;
4200 va_start(vargs, format);
sewardj0ec07f32006-01-12 12:32:32 +00004201 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE,
sewardj9af10a12006-02-01 14:59:42 +00004202 (unsigned long)format, (unsigned long)vargs,
4203 0, 0, 0);
fitzhardinge39de4b42003-10-31 07:12:21 +00004204 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00004205 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00004206}
4207
fitzhardinge39de4b42003-10-31 07:12:21 +00004208#endif /* NVALGRIND */
sewardj18d75132002-05-16 11:06:21 +00004209
sewardj0ec07f32006-01-12 12:32:32 +00004210
njn3e884182003-04-15 13:03:23 +00004211/* These requests allow control to move from the simulated CPU to the
njn1319b492006-11-20 22:02:40 +00004212 real CPU, calling an arbitary function.
4213
4214 Note that the current ThreadId is inserted as the first argument.
4215 So this call:
4216
4217 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
4218
4219 requires f to have this signature:
4220
4221 Word f(Word tid, Word arg1, Word arg2)
4222
4223 where "Word" is a word-sized type.
njn45fb4d32007-12-05 21:51:50 +00004224
4225 Note that these client requests are not entirely reliable. For example,
4226 if you call a function with them that subsequently calls printf(),
4227 there's a high chance Valgrind will crash. Generally, your prospects of
4228 these working are made higher if the called function does not refer to
4229 any global variables, and does not refer to any libc or other functions
4230 (printf et al). Any kind of entanglement with libc or dynamic linking is
4231 likely to have a bad outcome, for tricky reasons which we've grappled
4232 with a lot in the past.
njn1319b492006-11-20 22:02:40 +00004233*/
sewardj0ec07f32006-01-12 12:32:32 +00004234#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
sewardj315dc8d2006-08-28 21:13:06 +00004235 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004236 ({unsigned long _qyy_res; \
4237 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4238 VG_USERREQ__CLIENT_CALL0, \
4239 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004240 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004241 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004242 })
4243
sewardj0ec07f32006-01-12 12:32:32 +00004244#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
sewardj315dc8d2006-08-28 21:13:06 +00004245 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004246 ({unsigned long _qyy_res; \
4247 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4248 VG_USERREQ__CLIENT_CALL1, \
4249 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004250 _qyy_arg1, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004251 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004252 })
4253
sewardj0ec07f32006-01-12 12:32:32 +00004254#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
sewardj315dc8d2006-08-28 21:13:06 +00004255 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004256 ({unsigned long _qyy_res; \
4257 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4258 VG_USERREQ__CLIENT_CALL2, \
4259 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004260 _qyy_arg1, _qyy_arg2, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004261 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004262 })
4263
sewardj0ec07f32006-01-12 12:32:32 +00004264#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
sewardj315dc8d2006-08-28 21:13:06 +00004265 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004266 ({unsigned long _qyy_res; \
4267 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4268 VG_USERREQ__CLIENT_CALL3, \
4269 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004270 _qyy_arg1, _qyy_arg2, \
4271 _qyy_arg3, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004272 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004273 })
4274
4275
nethercote7cc9c232004-01-21 15:08:04 +00004276/* Counts the number of errors that have been recorded by a tool. Nb:
4277 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00004278 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00004279#define VALGRIND_COUNT_ERRORS \
sewardj315dc8d2006-08-28 21:13:06 +00004280 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004281 ({unsigned int _qyy_res; \
4282 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4283 VG_USERREQ__COUNT_ERRORS, \
sewardj9af10a12006-02-01 14:59:42 +00004284 0, 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004285 _qyy_res; \
njn47363ab2003-04-21 13:24:40 +00004286 })
4287
njn3ac96952009-07-09 23:35:44 +00004288/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
4289 when heap blocks are allocated in order to give accurate results. This
4290 happens automatically for the standard allocator functions such as
4291 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
4292 delete[], etc.
njnd7994182003-10-02 13:44:04 +00004293
njn3ac96952009-07-09 23:35:44 +00004294 But if your program uses a custom allocator, this doesn't automatically
4295 happen, and Valgrind will not do as well. For example, if you allocate
4296 superblocks with mmap() and then allocates chunks of the superblocks, all
4297 Valgrind's observations will be at the mmap() level and it won't know that
4298 the chunks should be considered separate entities. In Memcheck's case,
4299 that means you probably won't get heap block overrun detection (because
4300 there won't be redzones marked as unaddressable) and you definitely won't
4301 get any leak detection.
4302
4303 The following client requests allow a custom allocator to be annotated so
4304 that it can be handled accurately by Valgrind.
4305
4306 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
4307 by a malloc()-like function. For Memcheck (an illustrative case), this
4308 does two things:
4309
4310 - It records that the block has been allocated. This means any addresses
4311 within the block mentioned in error messages will be
4312 identified as belonging to the block. It also means that if the block
4313 isn't freed it will be detected by the leak checker.
4314
4315 - It marks the block as being addressable and undefined (if 'is_zeroed' is
4316 not set), or addressable and defined (if 'is_zeroed' is set). This
4317 controls how accesses to the block by the program are handled.
4318
4319 'addr' is the start of the usable block (ie. after any
4320 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
4321 can apply redzones -- these are blocks of padding at the start and end of
4322 each block. Adding redzones is recommended as it makes it much more likely
4323 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
4324 zeroed (or filled with another predictable value), as is the case for
4325 calloc().
4326
4327 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
4328 heap block -- that will be used by the client program -- is allocated.
4329 It's best to put it at the outermost level of the allocator if possible;
4330 for example, if you have a function my_alloc() which calls
4331 internal_alloc(), and the client request is put inside internal_alloc(),
4332 stack traces relating to the heap block will contain entries for both
4333 my_alloc() and internal_alloc(), which is probably not what you want.
4334
njnb965efb2009-08-10 07:36:54 +00004335 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
4336 custom blocks from within a heap block, B, that has been allocated with
4337 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
4338 -- the custom blocks will take precedence.
4339
njn3ac96952009-07-09 23:35:44 +00004340 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
4341 Memcheck, it does two things:
4342
4343 - It records that the block has been deallocated. This assumes that the
4344 block was annotated as having been allocated via
4345 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
4346
4347 - It marks the block as being unaddressable.
4348
4349 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
4350 heap block is deallocated.
4351
4352 In many cases, these two client requests will not be enough to get your
4353 allocator working well with Memcheck. More specifically, if your allocator
4354 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
4355 will be necessary to mark the memory as addressable just before the zeroing
4356 occurs, otherwise you'll get a lot of invalid write errors. For example,
4357 you'll need to do this if your allocator recycles freed blocks, but it
4358 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
4359 Alternatively, if your allocator reuses freed blocks for allocator-internal
4360 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
4361
4362 Really, what's happening is a blurring of the lines between the client
4363 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
4364 memory should be considered unaddressable to the client program, but the
4365 allocator knows more than the rest of the client program and so may be able
4366 to safely access it. Extra client requests are necessary for Valgrind to
4367 understand the distinction between the allocator and the rest of the
4368 program.
4369
4370 Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it
4371 has to be emulated with MALLOCLIKE/FREELIKE and memory copying.
4372
njn32f8d8c2009-07-15 02:31:45 +00004373 Ignored if addr == 0.
njn3ac96952009-07-09 23:35:44 +00004374*/
sewardj0ec07f32006-01-12 12:32:32 +00004375#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
4376 {unsigned int _qzz_res; \
4377 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4378 VG_USERREQ__MALLOCLIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00004379 addr, sizeB, rzB, is_zeroed, 0); \
njnd7994182003-10-02 13:44:04 +00004380 }
4381
njn32f8d8c2009-07-15 02:31:45 +00004382/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
4383 Ignored if addr == 0.
4384*/
sewardj0ec07f32006-01-12 12:32:32 +00004385#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
4386 {unsigned int _qzz_res; \
4387 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4388 VG_USERREQ__FREELIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00004389 addr, rzB, 0, 0, 0); \
njnd7994182003-10-02 13:44:04 +00004390 }
4391
rjwalshbc0bb832004-06-19 18:12:36 +00004392/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004393#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
4394 {unsigned int _qzz_res; \
4395 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4396 VG_USERREQ__CREATE_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00004397 pool, rzB, is_zeroed, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004398 }
4399
4400/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004401#define VALGRIND_DESTROY_MEMPOOL(pool) \
4402 {unsigned int _qzz_res; \
4403 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4404 VG_USERREQ__DESTROY_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00004405 pool, 0, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004406 }
4407
4408/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004409#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
4410 {unsigned int _qzz_res; \
4411 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4412 VG_USERREQ__MEMPOOL_ALLOC, \
sewardj9af10a12006-02-01 14:59:42 +00004413 pool, addr, size, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004414 }
4415
4416/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004417#define VALGRIND_MEMPOOL_FREE(pool, addr) \
4418 {unsigned int _qzz_res; \
4419 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4420 VG_USERREQ__MEMPOOL_FREE, \
sewardj9af10a12006-02-01 14:59:42 +00004421 pool, addr, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004422 }
4423
sewardj2c1c9df2006-07-28 00:06:37 +00004424/* Disassociate any pieces outside a particular range. */
4425#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
4426 {unsigned int _qzz_res; \
4427 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4428 VG_USERREQ__MEMPOOL_TRIM, \
4429 pool, addr, size, 0, 0); \
4430 }
4431
sewardjc740d762006-10-05 17:59:23 +00004432/* Resize and/or move a piece associated with a memory pool. */
4433#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
4434 {unsigned int _qzz_res; \
4435 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4436 VG_USERREQ__MOVE_MEMPOOL, \
4437 poolA, poolB, 0, 0, 0); \
4438 }
4439
4440/* Resize and/or move a piece associated with a memory pool. */
4441#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
4442 {unsigned int _qzz_res; \
4443 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4444 VG_USERREQ__MEMPOOL_CHANGE, \
4445 pool, addrA, addrB, size, 0); \
4446 }
4447
4448/* Return 1 if a mempool exists, else 0. */
4449#define VALGRIND_MEMPOOL_EXISTS(pool) \
njn44862972009-02-23 02:08:24 +00004450 __extension__ \
sewardjc740d762006-10-05 17:59:23 +00004451 ({unsigned int _qzz_res; \
4452 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4453 VG_USERREQ__MEMPOOL_EXISTS, \
4454 pool, 0, 0, 0, 0); \
4455 _qzz_res; \
4456 })
4457
rjwalsh0140af52005-06-04 20:42:33 +00004458/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004459#define VALGRIND_STACK_REGISTER(start, end) \
njn44862972009-02-23 02:08:24 +00004460 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004461 ({unsigned int _qzz_res; \
4462 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4463 VG_USERREQ__STACK_REGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00004464 start, end, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004465 _qzz_res; \
rjwalsh0140af52005-06-04 20:42:33 +00004466 })
4467
4468/* Unmark the piece of memory associated with a stack id as being a
4469 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00004470#define VALGRIND_STACK_DEREGISTER(id) \
4471 {unsigned int _qzz_res; \
4472 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4473 VG_USERREQ__STACK_DEREGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00004474 id, 0, 0, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00004475 }
4476
4477/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004478#define VALGRIND_STACK_CHANGE(id, start, end) \
4479 {unsigned int _qzz_res; \
4480 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4481 VG_USERREQ__STACK_CHANGE, \
sewardj9af10a12006-02-01 14:59:42 +00004482 id, start, end, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00004483 }
4484
sewardjc8259b82009-04-22 22:42:10 +00004485/* Load PDB debug info for Wine PE image_map. */
4486#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
4487 {unsigned int _qzz_res; \
4488 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4489 VG_USERREQ__LOAD_PDB_DEBUGINFO, \
4490 fd, ptr, total_size, delta, 0); \
4491 }
4492
sewardj0ec07f32006-01-12 12:32:32 +00004493
sewardjf5c1a7f2006-10-17 01:32:48 +00004494#undef PLAT_x86_linux
4495#undef PLAT_amd64_linux
4496#undef PLAT_ppc32_linux
4497#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +00004498#undef PLAT_arm_linux
sewardjf5c1a7f2006-10-17 01:32:48 +00004499#undef PLAT_ppc32_aix5
4500#undef PLAT_ppc64_aix5
sewardj0ec07f32006-01-12 12:32:32 +00004501
njn3e884182003-04-15 13:03:23 +00004502#endif /* __VALGRIND_H */