blob: 9cc0af9b38978b156c033a356ac099f08f2fe7f9 [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
sewardje4b0bf02006-06-05 23:21:15 +000015 Copyright (C) 2000-2006 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
sewardjf5c1a7f2006-10-17 01:32:48 +000087 latter (on Linux, that is). */
88#undef PLAT_x86_linux
89#undef PLAT_amd64_linux
90#undef PLAT_ppc32_linux
91#undef PLAT_ppc64_linux
92#undef PLAT_ppc32_aix5
93#undef PLAT_ppc64_aix5
sewardj0ec07f32006-01-12 12:32:32 +000094
sewardjf5c1a7f2006-10-17 01:32:48 +000095#if !defined(_AIX) && defined(__i386__)
96# define PLAT_x86_linux 1
97#elif !defined(_AIX) && defined(__x86_64__)
98# define PLAT_amd64_linux 1
99#elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__)
100# define PLAT_ppc32_linux 1
101#elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__)
102# define PLAT_ppc64_linux 1
103#elif defined(_AIX) && defined(__64BIT__)
104# define PLAT_ppc64_aix5 1
105#elif defined(_AIX) && !defined(__64BIT__)
106# define PLAT_ppc32_aix5 1
sewardjb5f6f512005-03-10 23:59:00 +0000107#endif
108
sewardjf5c1a7f2006-10-17 01:32:48 +0000109
110/* If we're not compiling for our target platform, don't generate
sewardj0ec07f32006-01-12 12:32:32 +0000111 any inline asms. */
sewardjf5c1a7f2006-10-17 01:32:48 +0000112#if !defined(PLAT_x86_linux) && !defined(PLAT_amd64_linux) \
113 && !defined(PLAT_ppc32_linux) && !defined(PLAT_ppc64_linux) \
114 && !defined(PLAT_ppc32_aix5) && !defined(PLAT_ppc64_aix5)
sewardj0ec07f32006-01-12 12:32:32 +0000115# if !defined(NVALGRIND)
116# define NVALGRIND 1
117# endif
118#endif
119
120
njn30d76c62005-06-18 15:07:39 +0000121/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000122/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
123/* in here of use to end-users -- skip to the next section. */
njn30d76c62005-06-18 15:07:39 +0000124/* ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000125
sewardj0ec07f32006-01-12 12:32:32 +0000126#if defined(NVALGRIND)
njn26aba4d2005-05-16 13:31:23 +0000127
128/* Define NVALGRIND to completely remove the Valgrind magic sequence
sewardj0ec07f32006-01-12 12:32:32 +0000129 from the compiled code (analogous to NDEBUG's effects on
130 assert()) */
131#define VALGRIND_DO_CLIENT_REQUEST( \
132 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000133 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000134 { \
135 (_zzq_rlval) = (_zzq_default); \
njn26aba4d2005-05-16 13:31:23 +0000136 }
137
sewardj0ec07f32006-01-12 12:32:32 +0000138#else /* ! NVALGRIND */
nethercotee90c6832004-10-18 18:07:49 +0000139
sewardj0ec07f32006-01-12 12:32:32 +0000140/* The following defines the magic code sequences which the JITter
141 spots and handles magically. Don't look too closely at them as
142 they will rot your brain.
143
144 The assembly code sequences for all architectures is in this one
145 file. This is because this file must be stand-alone, and we don't
146 want to have multiple files.
147
148 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
149 value gets put in the return slot, so that everything works when
150 this is executed not under Valgrind. Args are passed in a memory
151 block, and so there's no intrinsic limit to the number that could
sewardj9af10a12006-02-01 14:59:42 +0000152 be passed, but it's currently five.
nethercotee90c6832004-10-18 18:07:49 +0000153
nethercote54265442004-10-26 12:56:58 +0000154 The macro args are:
155 _zzq_rlval result lvalue
156 _zzq_default default value (result returned when running on real CPU)
157 _zzq_request request code
sewardj9af10a12006-02-01 14:59:42 +0000158 _zzq_arg1..5 request params
nethercote54265442004-10-26 12:56:58 +0000159
sewardj0ec07f32006-01-12 12:32:32 +0000160 The other two macros are used to support function wrapping, and are
sewardjd68ac3e2006-01-20 14:31:57 +0000161 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
162 guest's NRADDR pseudo-register and whatever other information is
163 needed to safely run the call original from the wrapper: on
164 ppc64-linux, the R2 value at the divert point is also needed. This
165 information is abstracted into a user-visible type, OrigFn.
166
167 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
168 guest, but guarantees that the branch instruction will not be
169 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
170 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
171 complete inline asm, since it needs to be combined with more magic
172 inline asm stuff to be useful.
nethercotee90c6832004-10-18 18:07:49 +0000173*/
174
sewardjf5c1a7f2006-10-17 01:32:48 +0000175/* ------------------------- x86-linux ------------------------- */
sewardjde4a4ab2005-03-23 13:10:32 +0000176
sewardjf5c1a7f2006-10-17 01:32:48 +0000177#if defined(PLAT_x86_linux)
sewardjc8858442006-01-20 15:17:20 +0000178
179typedef
180 struct {
181 unsigned int nraddr; /* where's the code? */
182 }
183 OrigFn;
184
sewardj0ec07f32006-01-12 12:32:32 +0000185#define __SPECIAL_INSTRUCTION_PREAMBLE \
186 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000187 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000188
sewardj0ec07f32006-01-12 12:32:32 +0000189#define VALGRIND_DO_CLIENT_REQUEST( \
190 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000191 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
192 { volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000193 volatile unsigned int _zzq_result; \
194 _zzq_args[0] = (unsigned int)(_zzq_request); \
195 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
196 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
197 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
198 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000199 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000200 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
201 /* %EDX = client_request ( %EAX ) */ \
202 "xchgl %%ebx,%%ebx" \
203 : "=d" (_zzq_result) \
204 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
205 : "cc", "memory" \
206 ); \
207 _zzq_rlval = _zzq_result; \
cerion85665ca2005-06-20 15:51:07 +0000208 }
sewardj2c48c7b2005-11-29 13:05:56 +0000209
sewardjc8858442006-01-20 15:17:20 +0000210#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
211 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
212 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000213 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
214 /* %EAX = guest_NRADDR */ \
215 "xchgl %%ecx,%%ecx" \
216 : "=a" (__addr) \
217 : \
218 : "cc", "memory" \
219 ); \
sewardjc8858442006-01-20 15:17:20 +0000220 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000221 }
sewardj0ec07f32006-01-12 12:32:32 +0000222
223#define VALGRIND_CALL_NOREDIR_EAX \
224 __SPECIAL_INSTRUCTION_PREAMBLE \
225 /* call-noredir *%EAX */ \
226 "xchgl %%edx,%%edx\n\t"
sewardjf5c1a7f2006-10-17 01:32:48 +0000227#endif /* PLAT_x86_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000228
sewardjf5c1a7f2006-10-17 01:32:48 +0000229/* ------------------------ amd64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000230
sewardjf5c1a7f2006-10-17 01:32:48 +0000231#if defined(PLAT_amd64_linux)
sewardjc8858442006-01-20 15:17:20 +0000232
233typedef
234 struct {
235 unsigned long long int nraddr; /* where's the code? */
236 }
237 OrigFn;
238
sewardj0ec07f32006-01-12 12:32:32 +0000239#define __SPECIAL_INSTRUCTION_PREAMBLE \
240 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000241 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000242
243#define VALGRIND_DO_CLIENT_REQUEST( \
244 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000245 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
246 { volatile unsigned long long int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000247 volatile unsigned long long int _zzq_result; \
248 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
249 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
250 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
251 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
252 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000253 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000254 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
255 /* %RDX = client_request ( %RAX ) */ \
256 "xchgq %%rbx,%%rbx" \
257 : "=d" (_zzq_result) \
258 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
259 : "cc", "memory" \
260 ); \
261 _zzq_rlval = _zzq_result; \
262 }
263
sewardjc8858442006-01-20 15:17:20 +0000264#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
265 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
266 volatile unsigned long long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000267 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
268 /* %RAX = guest_NRADDR */ \
269 "xchgq %%rcx,%%rcx" \
270 : "=a" (__addr) \
271 : \
272 : "cc", "memory" \
273 ); \
sewardjc8858442006-01-20 15:17:20 +0000274 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000275 }
276
277#define VALGRIND_CALL_NOREDIR_RAX \
278 __SPECIAL_INSTRUCTION_PREAMBLE \
279 /* call-noredir *%RAX */ \
280 "xchgq %%rdx,%%rdx\n\t"
sewardjf5c1a7f2006-10-17 01:32:48 +0000281#endif /* PLAT_amd64_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000282
sewardjf5c1a7f2006-10-17 01:32:48 +0000283/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000284
sewardjf5c1a7f2006-10-17 01:32:48 +0000285#if defined(PLAT_ppc32_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000286
287typedef
288 struct {
sewardjc8858442006-01-20 15:17:20 +0000289 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000290 }
291 OrigFn;
292
sewardj0ec07f32006-01-12 12:32:32 +0000293#define __SPECIAL_INSTRUCTION_PREAMBLE \
294 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000295 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000296
297#define VALGRIND_DO_CLIENT_REQUEST( \
298 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000299 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000300 \
sewardj9af10a12006-02-01 14:59:42 +0000301 { unsigned int _zzq_args[6]; \
sewardj1a85f4f2006-01-12 21:15:35 +0000302 register unsigned int _zzq_result __asm__("r3"); \
303 register unsigned int* _zzq_ptr __asm__("r4"); \
sewardj0ec07f32006-01-12 12:32:32 +0000304 _zzq_args[0] = (unsigned int)(_zzq_request); \
305 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
306 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
307 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
308 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000309 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000310 _zzq_ptr = _zzq_args; \
311 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
312 /* %R3 = client_request ( %R4 ) */ \
313 "or 1,1,1" \
314 : "=r" (_zzq_result) \
315 : "0" (_zzq_default), "r" (_zzq_ptr) \
316 : "cc", "memory"); \
317 _zzq_rlval = _zzq_result; \
318 }
319
sewardjd68ac3e2006-01-20 14:31:57 +0000320#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
321 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
322 register unsigned int __addr __asm__("r3"); \
sewardj0ec07f32006-01-12 12:32:32 +0000323 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
324 /* %R3 = guest_NRADDR */ \
325 "or 2,2,2" \
326 : "=r" (__addr) \
327 : \
328 : "cc", "memory" \
329 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000330 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000331 }
332
333#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
334 __SPECIAL_INSTRUCTION_PREAMBLE \
335 /* branch-and-link-to-noredir *%R11 */ \
336 "or 3,3,3\n\t"
sewardjf5c1a7f2006-10-17 01:32:48 +0000337#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000338
sewardjf5c1a7f2006-10-17 01:32:48 +0000339/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000340
sewardjf5c1a7f2006-10-17 01:32:48 +0000341#if defined(PLAT_ppc64_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000342
343typedef
344 struct {
345 unsigned long long int nraddr; /* where's the code? */
346 unsigned long long int r2; /* what tocptr do we need? */
347 }
348 OrigFn;
349
sewardj1a85f4f2006-01-12 21:15:35 +0000350#define __SPECIAL_INSTRUCTION_PREAMBLE \
351 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
352 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
353
sewardj0ec07f32006-01-12 12:32:32 +0000354#define VALGRIND_DO_CLIENT_REQUEST( \
355 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000356 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000357 \
sewardj9af10a12006-02-01 14:59:42 +0000358 { unsigned long long int _zzq_args[6]; \
sewardj1a85f4f2006-01-12 21:15:35 +0000359 register unsigned long long int _zzq_result __asm__("r3"); \
360 register unsigned long long int* _zzq_ptr __asm__("r4"); \
361 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
362 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
363 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
364 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
365 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000366 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000367 _zzq_ptr = _zzq_args; \
sewardj1a85f4f2006-01-12 21:15:35 +0000368 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
369 /* %R3 = client_request ( %R4 ) */ \
370 "or 1,1,1" \
371 : "=r" (_zzq_result) \
sewardj0ec07f32006-01-12 12:32:32 +0000372 : "0" (_zzq_default), "r" (_zzq_ptr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000373 : "cc", "memory"); \
374 _zzq_rlval = _zzq_result; \
sewardj0ec07f32006-01-12 12:32:32 +0000375 }
sewardj1a85f4f2006-01-12 21:15:35 +0000376
sewardjd68ac3e2006-01-20 14:31:57 +0000377#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
378 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
379 register unsigned long long int __addr __asm__("r3"); \
sewardj1a85f4f2006-01-12 21:15:35 +0000380 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
381 /* %R3 = guest_NRADDR */ \
382 "or 2,2,2" \
383 : "=r" (__addr) \
384 : \
385 : "cc", "memory" \
386 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000387 _zzq_orig->nraddr = __addr; \
388 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
389 /* %R3 = guest_NRADDR_GPR2 */ \
390 "or 4,4,4" \
391 : "=r" (__addr) \
392 : \
393 : "cc", "memory" \
394 ); \
395 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000396 }
397
398#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
399 __SPECIAL_INSTRUCTION_PREAMBLE \
400 /* branch-and-link-to-noredir *%R11 */ \
401 "or 3,3,3\n\t"
402
sewardjf5c1a7f2006-10-17 01:32:48 +0000403#endif /* PLAT_ppc64_linux */
cerion85665ca2005-06-20 15:51:07 +0000404
sewardjf5c1a7f2006-10-17 01:32:48 +0000405/* ------------------------ ppc32-aix5 ------------------------- */
406
407#if defined(PLAT_ppc32_aix5)
408
409typedef
410 struct {
411 unsigned int nraddr; /* where's the code? */
412 unsigned int r2; /* what tocptr do we need? */
413 }
414 OrigFn;
415
416#define __SPECIAL_INSTRUCTION_PREAMBLE \
417 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
418 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
419
420#define VALGRIND_DO_CLIENT_REQUEST( \
421 _zzq_rlval, _zzq_default, _zzq_request, \
422 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
423 \
424 { unsigned int _zzq_args[7]; \
425 register unsigned int _zzq_result; \
426 register unsigned int* _zzq_ptr; \
427 _zzq_args[0] = (unsigned int)(_zzq_request); \
428 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
429 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
430 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
431 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
432 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
433 _zzq_args[6] = (unsigned int)(_zzq_default); \
434 _zzq_ptr = _zzq_args; \
435 __asm__ volatile("mr 4,%1\n\t" \
436 "lwz 3, 24(4)\n\t" \
437 __SPECIAL_INSTRUCTION_PREAMBLE \
438 /* %R3 = client_request ( %R4 ) */ \
439 "or 1,1,1\n\t" \
440 "mr %0,3" \
441 : "=b" (_zzq_result) \
442 : "b" (_zzq_ptr) \
443 : "r3", "r4", "cc", "memory"); \
444 _zzq_rlval = _zzq_result; \
445 }
446
447#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
448 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
449 register unsigned int __addr; \
450 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
451 /* %R3 = guest_NRADDR */ \
452 "or 2,2,2\n\t" \
453 "mr %0,3" \
454 : "=b" (__addr) \
455 : \
456 : "r3", "cc", "memory" \
457 ); \
458 _zzq_orig->nraddr = __addr; \
459 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
460 /* %R3 = guest_NRADDR_GPR2 */ \
461 "or 4,4,4\n\t" \
462 "mr %0,3" \
463 : "=b" (__addr) \
464 : \
465 : "r3", "cc", "memory" \
466 ); \
467 _zzq_orig->r2 = __addr; \
468 }
469
470#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
471 __SPECIAL_INSTRUCTION_PREAMBLE \
472 /* branch-and-link-to-noredir *%R11 */ \
473 "or 3,3,3\n\t"
474
475#endif /* PLAT_ppc32_aix5 */
476
477/* ------------------------ ppc64-aix5 ------------------------- */
478
479#if defined(PLAT_ppc64_aix5)
480
481typedef
482 struct {
483 unsigned long long int nraddr; /* where's the code? */
484 unsigned long long int r2; /* what tocptr do we need? */
485 }
486 OrigFn;
487
488#define __SPECIAL_INSTRUCTION_PREAMBLE \
489 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
490 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
491
492#define VALGRIND_DO_CLIENT_REQUEST( \
493 _zzq_rlval, _zzq_default, _zzq_request, \
494 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
495 \
496 { unsigned long long int _zzq_args[7]; \
497 register unsigned long long int _zzq_result; \
498 register unsigned long long int* _zzq_ptr; \
499 _zzq_args[0] = (unsigned int long long)(_zzq_request); \
500 _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
501 _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
502 _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
503 _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
504 _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
505 _zzq_args[6] = (unsigned int long long)(_zzq_default); \
506 _zzq_ptr = _zzq_args; \
507 __asm__ volatile("mr 4,%1\n\t" \
508 "ld 3, 48(4)\n\t" \
509 __SPECIAL_INSTRUCTION_PREAMBLE \
510 /* %R3 = client_request ( %R4 ) */ \
511 "or 1,1,1\n\t" \
512 "mr %0,3" \
513 : "=b" (_zzq_result) \
514 : "b" (_zzq_ptr) \
515 : "r3", "r4", "cc", "memory"); \
516 _zzq_rlval = _zzq_result; \
517 }
518
519#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
520 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
521 register unsigned long long int __addr; \
522 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
523 /* %R3 = guest_NRADDR */ \
524 "or 2,2,2\n\t" \
525 "mr %0,3" \
526 : "=b" (__addr) \
527 : \
528 : "r3", "cc", "memory" \
529 ); \
530 _zzq_orig->nraddr = __addr; \
531 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
532 /* %R3 = guest_NRADDR_GPR2 */ \
533 "or 4,4,4\n\t" \
534 "mr %0,3" \
535 : "=b" (__addr) \
536 : \
537 : "r3", "cc", "memory" \
538 ); \
539 _zzq_orig->r2 = __addr; \
540 }
541
542#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
543 __SPECIAL_INSTRUCTION_PREAMBLE \
544 /* branch-and-link-to-noredir *%R11 */ \
545 "or 3,3,3\n\t"
546
547#endif /* PLAT_ppc64_aix5 */
548
549/* Insert assembly code for other platforms here... */
njn26aba4d2005-05-16 13:31:23 +0000550
sewardj37091fb2002-11-16 11:06:50 +0000551#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +0000552
nethercote69d9c462004-10-26 13:00:12 +0000553
njn30d76c62005-06-18 15:07:39 +0000554/* ------------------------------------------------------------------ */
sewardjf5c1a7f2006-10-17 01:32:48 +0000555/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
sewardj0ec07f32006-01-12 12:32:32 +0000556/* ugly. It's the least-worst tradeoff I can think of. */
557/* ------------------------------------------------------------------ */
558
559/* This section defines magic (a.k.a appalling-hack) macros for doing
560 guaranteed-no-redirection macros, so as to get from function
561 wrappers to the functions they are wrapping. The whole point is to
562 construct standard call sequences, but to do the call itself with a
563 special no-redirect call pseudo-instruction that the JIT
564 understands and handles specially. This section is long and
565 repetitious, and I can't see a way to make it shorter.
566
567 The naming scheme is as follows:
568
569 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
570
571 'W' stands for "word" and 'v' for "void". Hence there are
572 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
573 and for each, the possibility of returning a word-typed result, or
574 no result.
575*/
576
577/* Use these to write the name of your wrapper. NOTE: duplicates
578 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
579
580#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
581 _vgwZU_##soname##_##fnname
582
583#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
584 _vgwZZ_##soname##_##fnname
585
sewardjd68ac3e2006-01-20 14:31:57 +0000586/* Use this macro from within a wrapper function to collect the
587 context (address and possibly other info) of the original function.
588 Once you have that you can then use it in one of the CALL_FN_
589 macros. The type of the argument _lval is OrigFn. */
590#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +0000591
592/* Derivatives of the main macros below, for calling functions
593 returning void. */
594
595#define CALL_FN_v_v(fnptr) \
596 do { volatile unsigned long _junk; \
597 CALL_FN_W_v(_junk,fnptr); } while (0)
598
599#define CALL_FN_v_W(fnptr, arg1) \
600 do { volatile unsigned long _junk; \
601 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
602
603#define CALL_FN_v_WW(fnptr, arg1,arg2) \
604 do { volatile unsigned long _junk; \
605 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
606
sewardj5ce4b152006-03-11 12:57:41 +0000607#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
608 do { volatile unsigned long _junk; \
609 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
610
sewardjf5c1a7f2006-10-17 01:32:48 +0000611/* ------------------------- x86-linux ------------------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000612
sewardjf5c1a7f2006-10-17 01:32:48 +0000613#if defined(PLAT_x86_linux)
sewardj0ec07f32006-01-12 12:32:32 +0000614
615/* These regs are trashed by the hidden call. No need to mention eax
616 as gcc can already see that, plus causes gcc to bomb. */
617#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
618
619/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
620 long) == 4. */
621
sewardj66226cc2006-01-20 15:46:46 +0000622#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +0000623 do { \
sewardj66226cc2006-01-20 15:46:46 +0000624 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000625 volatile unsigned long _argvec[1]; \
626 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000627 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000628 __asm__ volatile( \
629 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
630 VALGRIND_CALL_NOREDIR_EAX \
631 : /*out*/ "=a" (_res) \
632 : /*in*/ "a" (&_argvec[0]) \
633 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
634 ); \
635 lval = (__typeof__(lval)) _res; \
636 } while (0)
637
sewardj66226cc2006-01-20 15:46:46 +0000638#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +0000639 do { \
sewardj66226cc2006-01-20 15:46:46 +0000640 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000641 volatile unsigned long _argvec[2]; \
642 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000643 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000644 _argvec[1] = (unsigned long)(arg1); \
645 __asm__ volatile( \
646 "pushl 4(%%eax)\n\t" \
647 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
648 VALGRIND_CALL_NOREDIR_EAX \
649 "addl $4, %%esp\n" \
650 : /*out*/ "=a" (_res) \
651 : /*in*/ "a" (&_argvec[0]) \
652 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
653 ); \
654 lval = (__typeof__(lval)) _res; \
655 } while (0)
656
sewardj66226cc2006-01-20 15:46:46 +0000657#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +0000658 do { \
sewardj66226cc2006-01-20 15:46:46 +0000659 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000660 volatile unsigned long _argvec[3]; \
661 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000662 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000663 _argvec[1] = (unsigned long)(arg1); \
664 _argvec[2] = (unsigned long)(arg2); \
665 __asm__ volatile( \
666 "pushl 8(%%eax)\n\t" \
667 "pushl 4(%%eax)\n\t" \
668 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
669 VALGRIND_CALL_NOREDIR_EAX \
670 "addl $8, %%esp\n" \
671 : /*out*/ "=a" (_res) \
672 : /*in*/ "a" (&_argvec[0]) \
673 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
674 ); \
675 lval = (__typeof__(lval)) _res; \
676 } while (0)
677
sewardj9e8b07a2006-02-18 21:13:29 +0000678#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
679 do { \
680 volatile OrigFn _orig = (orig); \
681 volatile unsigned long _argvec[4]; \
682 volatile unsigned long _res; \
683 _argvec[0] = (unsigned long)_orig.nraddr; \
684 _argvec[1] = (unsigned long)(arg1); \
685 _argvec[2] = (unsigned long)(arg2); \
686 _argvec[3] = (unsigned long)(arg3); \
687 __asm__ volatile( \
688 "pushl 12(%%eax)\n\t" \
689 "pushl 8(%%eax)\n\t" \
690 "pushl 4(%%eax)\n\t" \
691 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
692 VALGRIND_CALL_NOREDIR_EAX \
693 "addl $12, %%esp\n" \
694 : /*out*/ "=a" (_res) \
695 : /*in*/ "a" (&_argvec[0]) \
696 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
697 ); \
698 lval = (__typeof__(lval)) _res; \
699 } while (0)
700
sewardj66226cc2006-01-20 15:46:46 +0000701#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
sewardj0ec07f32006-01-12 12:32:32 +0000702 do { \
sewardj66226cc2006-01-20 15:46:46 +0000703 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000704 volatile unsigned long _argvec[5]; \
705 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000706 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000707 _argvec[1] = (unsigned long)(arg1); \
708 _argvec[2] = (unsigned long)(arg2); \
709 _argvec[3] = (unsigned long)(arg3); \
710 _argvec[4] = (unsigned long)(arg4); \
711 __asm__ volatile( \
712 "pushl 16(%%eax)\n\t" \
713 "pushl 12(%%eax)\n\t" \
714 "pushl 8(%%eax)\n\t" \
715 "pushl 4(%%eax)\n\t" \
716 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
717 VALGRIND_CALL_NOREDIR_EAX \
718 "addl $16, %%esp\n" \
719 : /*out*/ "=a" (_res) \
720 : /*in*/ "a" (&_argvec[0]) \
721 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
722 ); \
723 lval = (__typeof__(lval)) _res; \
724 } while (0)
725
sewardj66226cc2006-01-20 15:46:46 +0000726#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000727 do { \
sewardj66226cc2006-01-20 15:46:46 +0000728 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000729 volatile unsigned long _argvec[6]; \
730 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000731 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000732 _argvec[1] = (unsigned long)(arg1); \
733 _argvec[2] = (unsigned long)(arg2); \
734 _argvec[3] = (unsigned long)(arg3); \
735 _argvec[4] = (unsigned long)(arg4); \
736 _argvec[5] = (unsigned long)(arg5); \
737 __asm__ volatile( \
738 "pushl 20(%%eax)\n\t" \
739 "pushl 16(%%eax)\n\t" \
740 "pushl 12(%%eax)\n\t" \
741 "pushl 8(%%eax)\n\t" \
742 "pushl 4(%%eax)\n\t" \
743 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
744 VALGRIND_CALL_NOREDIR_EAX \
745 "addl $20, %%esp\n" \
746 : /*out*/ "=a" (_res) \
747 : /*in*/ "a" (&_argvec[0]) \
748 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
749 ); \
750 lval = (__typeof__(lval)) _res; \
751 } while (0)
752
sewardj66226cc2006-01-20 15:46:46 +0000753#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +0000754 do { \
sewardj66226cc2006-01-20 15:46:46 +0000755 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000756 volatile unsigned long _argvec[7]; \
757 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000758 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000759 _argvec[1] = (unsigned long)(arg1); \
760 _argvec[2] = (unsigned long)(arg2); \
761 _argvec[3] = (unsigned long)(arg3); \
762 _argvec[4] = (unsigned long)(arg4); \
763 _argvec[5] = (unsigned long)(arg5); \
764 _argvec[6] = (unsigned long)(arg6); \
765 __asm__ volatile( \
766 "pushl 24(%%eax)\n\t" \
767 "pushl 20(%%eax)\n\t" \
768 "pushl 16(%%eax)\n\t" \
769 "pushl 12(%%eax)\n\t" \
770 "pushl 8(%%eax)\n\t" \
771 "pushl 4(%%eax)\n\t" \
772 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
773 VALGRIND_CALL_NOREDIR_EAX \
774 "addl $24, %%esp\n" \
775 : /*out*/ "=a" (_res) \
776 : /*in*/ "a" (&_argvec[0]) \
777 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
778 ); \
779 lval = (__typeof__(lval)) _res; \
780 } while (0)
781
sewardj66226cc2006-01-20 15:46:46 +0000782#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
783 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +0000784 do { \
sewardj66226cc2006-01-20 15:46:46 +0000785 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000786 volatile unsigned long _argvec[8]; \
787 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000788 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000789 _argvec[1] = (unsigned long)(arg1); \
790 _argvec[2] = (unsigned long)(arg2); \
791 _argvec[3] = (unsigned long)(arg3); \
792 _argvec[4] = (unsigned long)(arg4); \
793 _argvec[5] = (unsigned long)(arg5); \
794 _argvec[6] = (unsigned long)(arg6); \
795 _argvec[7] = (unsigned long)(arg7); \
796 __asm__ volatile( \
797 "pushl 28(%%eax)\n\t" \
798 "pushl 24(%%eax)\n\t" \
799 "pushl 20(%%eax)\n\t" \
800 "pushl 16(%%eax)\n\t" \
801 "pushl 12(%%eax)\n\t" \
802 "pushl 8(%%eax)\n\t" \
803 "pushl 4(%%eax)\n\t" \
804 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
805 VALGRIND_CALL_NOREDIR_EAX \
806 "addl $28, %%esp\n" \
807 : /*out*/ "=a" (_res) \
808 : /*in*/ "a" (&_argvec[0]) \
809 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
810 ); \
811 lval = (__typeof__(lval)) _res; \
812 } while (0)
813
sewardj66226cc2006-01-20 15:46:46 +0000814#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
815 arg7,arg8) \
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[9]; \
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 _argvec[6] = (unsigned long)(arg6); \
827 _argvec[7] = (unsigned long)(arg7); \
828 _argvec[8] = (unsigned long)(arg8); \
829 __asm__ volatile( \
830 "pushl 32(%%eax)\n\t" \
831 "pushl 28(%%eax)\n\t" \
832 "pushl 24(%%eax)\n\t" \
833 "pushl 20(%%eax)\n\t" \
834 "pushl 16(%%eax)\n\t" \
835 "pushl 12(%%eax)\n\t" \
836 "pushl 8(%%eax)\n\t" \
837 "pushl 4(%%eax)\n\t" \
838 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
839 VALGRIND_CALL_NOREDIR_EAX \
840 "addl $32, %%esp\n" \
841 : /*out*/ "=a" (_res) \
842 : /*in*/ "a" (&_argvec[0]) \
843 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
844 ); \
845 lval = (__typeof__(lval)) _res; \
846 } while (0)
847
sewardj45fa5b02006-03-09 19:06:23 +0000848#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
849 arg7,arg8,arg9) \
850 do { \
851 volatile OrigFn _orig = (orig); \
852 volatile unsigned long _argvec[10]; \
853 volatile unsigned long _res; \
854 _argvec[0] = (unsigned long)_orig.nraddr; \
855 _argvec[1] = (unsigned long)(arg1); \
856 _argvec[2] = (unsigned long)(arg2); \
857 _argvec[3] = (unsigned long)(arg3); \
858 _argvec[4] = (unsigned long)(arg4); \
859 _argvec[5] = (unsigned long)(arg5); \
860 _argvec[6] = (unsigned long)(arg6); \
861 _argvec[7] = (unsigned long)(arg7); \
862 _argvec[8] = (unsigned long)(arg8); \
863 _argvec[9] = (unsigned long)(arg9); \
864 __asm__ volatile( \
865 "pushl 36(%%eax)\n\t" \
866 "pushl 32(%%eax)\n\t" \
867 "pushl 28(%%eax)\n\t" \
868 "pushl 24(%%eax)\n\t" \
869 "pushl 20(%%eax)\n\t" \
870 "pushl 16(%%eax)\n\t" \
871 "pushl 12(%%eax)\n\t" \
872 "pushl 8(%%eax)\n\t" \
873 "pushl 4(%%eax)\n\t" \
874 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
875 VALGRIND_CALL_NOREDIR_EAX \
876 "addl $36, %%esp\n" \
877 : /*out*/ "=a" (_res) \
878 : /*in*/ "a" (&_argvec[0]) \
879 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
880 ); \
881 lval = (__typeof__(lval)) _res; \
882 } while (0)
883
884#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
885 arg7,arg8,arg9,arg10) \
886 do { \
887 volatile OrigFn _orig = (orig); \
888 volatile unsigned long _argvec[11]; \
889 volatile unsigned long _res; \
890 _argvec[0] = (unsigned long)_orig.nraddr; \
891 _argvec[1] = (unsigned long)(arg1); \
892 _argvec[2] = (unsigned long)(arg2); \
893 _argvec[3] = (unsigned long)(arg3); \
894 _argvec[4] = (unsigned long)(arg4); \
895 _argvec[5] = (unsigned long)(arg5); \
896 _argvec[6] = (unsigned long)(arg6); \
897 _argvec[7] = (unsigned long)(arg7); \
898 _argvec[8] = (unsigned long)(arg8); \
899 _argvec[9] = (unsigned long)(arg9); \
900 _argvec[10] = (unsigned long)(arg10); \
901 __asm__ volatile( \
902 "pushl 40(%%eax)\n\t" \
903 "pushl 36(%%eax)\n\t" \
904 "pushl 32(%%eax)\n\t" \
905 "pushl 28(%%eax)\n\t" \
906 "pushl 24(%%eax)\n\t" \
907 "pushl 20(%%eax)\n\t" \
908 "pushl 16(%%eax)\n\t" \
909 "pushl 12(%%eax)\n\t" \
910 "pushl 8(%%eax)\n\t" \
911 "pushl 4(%%eax)\n\t" \
912 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
913 VALGRIND_CALL_NOREDIR_EAX \
914 "addl $40, %%esp\n" \
915 : /*out*/ "=a" (_res) \
916 : /*in*/ "a" (&_argvec[0]) \
917 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
918 ); \
919 lval = (__typeof__(lval)) _res; \
920 } while (0)
921
sewardj5ce4b152006-03-11 12:57:41 +0000922#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
923 arg6,arg7,arg8,arg9,arg10, \
924 arg11) \
925 do { \
926 volatile OrigFn _orig = (orig); \
927 volatile unsigned long _argvec[12]; \
928 volatile unsigned long _res; \
929 _argvec[0] = (unsigned long)_orig.nraddr; \
930 _argvec[1] = (unsigned long)(arg1); \
931 _argvec[2] = (unsigned long)(arg2); \
932 _argvec[3] = (unsigned long)(arg3); \
933 _argvec[4] = (unsigned long)(arg4); \
934 _argvec[5] = (unsigned long)(arg5); \
935 _argvec[6] = (unsigned long)(arg6); \
936 _argvec[7] = (unsigned long)(arg7); \
937 _argvec[8] = (unsigned long)(arg8); \
938 _argvec[9] = (unsigned long)(arg9); \
939 _argvec[10] = (unsigned long)(arg10); \
940 _argvec[11] = (unsigned long)(arg11); \
941 __asm__ volatile( \
942 "pushl 44(%%eax)\n\t" \
943 "pushl 40(%%eax)\n\t" \
944 "pushl 36(%%eax)\n\t" \
945 "pushl 32(%%eax)\n\t" \
946 "pushl 28(%%eax)\n\t" \
947 "pushl 24(%%eax)\n\t" \
948 "pushl 20(%%eax)\n\t" \
949 "pushl 16(%%eax)\n\t" \
950 "pushl 12(%%eax)\n\t" \
951 "pushl 8(%%eax)\n\t" \
952 "pushl 4(%%eax)\n\t" \
953 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
954 VALGRIND_CALL_NOREDIR_EAX \
955 "addl $44, %%esp\n" \
956 : /*out*/ "=a" (_res) \
957 : /*in*/ "a" (&_argvec[0]) \
958 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
959 ); \
960 lval = (__typeof__(lval)) _res; \
961 } while (0)
962
sewardj66226cc2006-01-20 15:46:46 +0000963#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
964 arg6,arg7,arg8,arg9,arg10, \
965 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +0000966 do { \
sewardj66226cc2006-01-20 15:46:46 +0000967 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000968 volatile unsigned long _argvec[13]; \
969 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000970 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000971 _argvec[1] = (unsigned long)(arg1); \
972 _argvec[2] = (unsigned long)(arg2); \
973 _argvec[3] = (unsigned long)(arg3); \
974 _argvec[4] = (unsigned long)(arg4); \
975 _argvec[5] = (unsigned long)(arg5); \
976 _argvec[6] = (unsigned long)(arg6); \
977 _argvec[7] = (unsigned long)(arg7); \
978 _argvec[8] = (unsigned long)(arg8); \
979 _argvec[9] = (unsigned long)(arg9); \
980 _argvec[10] = (unsigned long)(arg10); \
981 _argvec[11] = (unsigned long)(arg11); \
982 _argvec[12] = (unsigned long)(arg12); \
983 __asm__ volatile( \
984 "pushl 48(%%eax)\n\t" \
985 "pushl 44(%%eax)\n\t" \
986 "pushl 40(%%eax)\n\t" \
987 "pushl 36(%%eax)\n\t" \
988 "pushl 32(%%eax)\n\t" \
989 "pushl 28(%%eax)\n\t" \
990 "pushl 24(%%eax)\n\t" \
991 "pushl 20(%%eax)\n\t" \
992 "pushl 16(%%eax)\n\t" \
993 "pushl 12(%%eax)\n\t" \
994 "pushl 8(%%eax)\n\t" \
995 "pushl 4(%%eax)\n\t" \
996 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
997 VALGRIND_CALL_NOREDIR_EAX \
998 "addl $48, %%esp\n" \
999 : /*out*/ "=a" (_res) \
1000 : /*in*/ "a" (&_argvec[0]) \
1001 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1002 ); \
1003 lval = (__typeof__(lval)) _res; \
1004 } while (0)
1005
sewardjf5c1a7f2006-10-17 01:32:48 +00001006#endif /* PLAT_x86_linux */
sewardj0ec07f32006-01-12 12:32:32 +00001007
sewardjf5c1a7f2006-10-17 01:32:48 +00001008/* ------------------------ amd64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00001009
sewardjf5c1a7f2006-10-17 01:32:48 +00001010#if defined(PLAT_amd64_linux)
sewardj0ec07f32006-01-12 12:32:32 +00001011
1012/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1013
1014/* These regs are trashed by the hidden call. */
1015#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1016 "rdi", "r8", "r9", "r10", "r11"
1017
1018/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1019 long) == 8. */
1020
sewardjc8858442006-01-20 15:17:20 +00001021#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001022 do { \
sewardjc8858442006-01-20 15:17:20 +00001023 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001024 volatile unsigned long _argvec[1]; \
1025 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001026 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001027 __asm__ volatile( \
1028 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1029 VALGRIND_CALL_NOREDIR_RAX \
1030 : /*out*/ "=a" (_res) \
1031 : /*in*/ "a" (&_argvec[0]) \
1032 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1033 ); \
1034 lval = (__typeof__(lval)) _res; \
1035 } while (0)
1036
sewardjc8858442006-01-20 15:17:20 +00001037#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001038 do { \
sewardjc8858442006-01-20 15:17:20 +00001039 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001040 volatile unsigned long _argvec[2]; \
1041 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001042 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001043 _argvec[1] = (unsigned long)(arg1); \
1044 __asm__ volatile( \
1045 "movq 8(%%rax), %%rdi\n\t" \
1046 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1047 VALGRIND_CALL_NOREDIR_RAX \
1048 : /*out*/ "=a" (_res) \
1049 : /*in*/ "a" (&_argvec[0]) \
1050 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1051 ); \
1052 lval = (__typeof__(lval)) _res; \
1053 } while (0)
1054
sewardjc8858442006-01-20 15:17:20 +00001055#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001056 do { \
sewardjc8858442006-01-20 15:17:20 +00001057 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001058 volatile unsigned long _argvec[3]; \
1059 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001060 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001061 _argvec[1] = (unsigned long)(arg1); \
1062 _argvec[2] = (unsigned long)(arg2); \
1063 __asm__ volatile( \
1064 "movq 16(%%rax), %%rsi\n\t" \
1065 "movq 8(%%rax), %%rdi\n\t" \
1066 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1067 VALGRIND_CALL_NOREDIR_RAX \
1068 : /*out*/ "=a" (_res) \
1069 : /*in*/ "a" (&_argvec[0]) \
1070 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1071 ); \
1072 lval = (__typeof__(lval)) _res; \
1073 } while (0)
1074
sewardja50f9dc2006-03-11 16:19:14 +00001075#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1076 do { \
1077 volatile OrigFn _orig = (orig); \
1078 volatile unsigned long _argvec[4]; \
1079 volatile unsigned long _res; \
1080 _argvec[0] = (unsigned long)_orig.nraddr; \
1081 _argvec[1] = (unsigned long)(arg1); \
1082 _argvec[2] = (unsigned long)(arg2); \
1083 _argvec[3] = (unsigned long)(arg3); \
1084 __asm__ volatile( \
1085 "movq 24(%%rax), %%rdx\n\t" \
1086 "movq 16(%%rax), %%rsi\n\t" \
1087 "movq 8(%%rax), %%rdi\n\t" \
1088 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1089 VALGRIND_CALL_NOREDIR_RAX \
1090 : /*out*/ "=a" (_res) \
1091 : /*in*/ "a" (&_argvec[0]) \
1092 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1093 ); \
1094 lval = (__typeof__(lval)) _res; \
1095 } while (0)
1096
1097#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1098 do { \
1099 volatile OrigFn _orig = (orig); \
1100 volatile unsigned long _argvec[5]; \
1101 volatile unsigned long _res; \
1102 _argvec[0] = (unsigned long)_orig.nraddr; \
1103 _argvec[1] = (unsigned long)(arg1); \
1104 _argvec[2] = (unsigned long)(arg2); \
1105 _argvec[3] = (unsigned long)(arg3); \
1106 _argvec[4] = (unsigned long)(arg4); \
1107 __asm__ volatile( \
1108 "movq 32(%%rax), %%rcx\n\t" \
1109 "movq 24(%%rax), %%rdx\n\t" \
1110 "movq 16(%%rax), %%rsi\n\t" \
1111 "movq 8(%%rax), %%rdi\n\t" \
1112 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1113 VALGRIND_CALL_NOREDIR_RAX \
1114 : /*out*/ "=a" (_res) \
1115 : /*in*/ "a" (&_argvec[0]) \
1116 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1117 ); \
1118 lval = (__typeof__(lval)) _res; \
1119 } while (0)
1120
1121#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1122 do { \
1123 volatile OrigFn _orig = (orig); \
1124 volatile unsigned long _argvec[6]; \
1125 volatile unsigned long _res; \
1126 _argvec[0] = (unsigned long)_orig.nraddr; \
1127 _argvec[1] = (unsigned long)(arg1); \
1128 _argvec[2] = (unsigned long)(arg2); \
1129 _argvec[3] = (unsigned long)(arg3); \
1130 _argvec[4] = (unsigned long)(arg4); \
1131 _argvec[5] = (unsigned long)(arg5); \
1132 __asm__ volatile( \
1133 "movq 40(%%rax), %%r8\n\t" \
1134 "movq 32(%%rax), %%rcx\n\t" \
1135 "movq 24(%%rax), %%rdx\n\t" \
1136 "movq 16(%%rax), %%rsi\n\t" \
1137 "movq 8(%%rax), %%rdi\n\t" \
1138 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1139 VALGRIND_CALL_NOREDIR_RAX \
1140 : /*out*/ "=a" (_res) \
1141 : /*in*/ "a" (&_argvec[0]) \
1142 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1143 ); \
1144 lval = (__typeof__(lval)) _res; \
1145 } while (0)
1146
1147#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1148 do { \
1149 volatile OrigFn _orig = (orig); \
1150 volatile unsigned long _argvec[7]; \
1151 volatile unsigned long _res; \
1152 _argvec[0] = (unsigned long)_orig.nraddr; \
1153 _argvec[1] = (unsigned long)(arg1); \
1154 _argvec[2] = (unsigned long)(arg2); \
1155 _argvec[3] = (unsigned long)(arg3); \
1156 _argvec[4] = (unsigned long)(arg4); \
1157 _argvec[5] = (unsigned long)(arg5); \
1158 _argvec[6] = (unsigned long)(arg6); \
1159 __asm__ volatile( \
1160 "movq 48(%%rax), %%r9\n\t" \
1161 "movq 40(%%rax), %%r8\n\t" \
1162 "movq 32(%%rax), %%rcx\n\t" \
1163 "movq 24(%%rax), %%rdx\n\t" \
1164 "movq 16(%%rax), %%rsi\n\t" \
1165 "movq 8(%%rax), %%rdi\n\t" \
1166 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1167 VALGRIND_CALL_NOREDIR_RAX \
1168 : /*out*/ "=a" (_res) \
1169 : /*in*/ "a" (&_argvec[0]) \
1170 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1171 ); \
1172 lval = (__typeof__(lval)) _res; \
1173 } while (0)
1174
1175#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1176 arg7) \
1177 do { \
1178 volatile OrigFn _orig = (orig); \
1179 volatile unsigned long _argvec[8]; \
1180 volatile unsigned long _res; \
1181 _argvec[0] = (unsigned long)_orig.nraddr; \
1182 _argvec[1] = (unsigned long)(arg1); \
1183 _argvec[2] = (unsigned long)(arg2); \
1184 _argvec[3] = (unsigned long)(arg3); \
1185 _argvec[4] = (unsigned long)(arg4); \
1186 _argvec[5] = (unsigned long)(arg5); \
1187 _argvec[6] = (unsigned long)(arg6); \
1188 _argvec[7] = (unsigned long)(arg7); \
1189 __asm__ volatile( \
1190 "pushq 56(%%rax)\n\t" \
1191 "movq 48(%%rax), %%r9\n\t" \
1192 "movq 40(%%rax), %%r8\n\t" \
1193 "movq 32(%%rax), %%rcx\n\t" \
1194 "movq 24(%%rax), %%rdx\n\t" \
1195 "movq 16(%%rax), %%rsi\n\t" \
1196 "movq 8(%%rax), %%rdi\n\t" \
1197 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1198 VALGRIND_CALL_NOREDIR_RAX \
1199 "addq $8, %%rsp\n" \
1200 : /*out*/ "=a" (_res) \
1201 : /*in*/ "a" (&_argvec[0]) \
1202 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1203 ); \
1204 lval = (__typeof__(lval)) _res; \
1205 } while (0)
1206
1207#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1208 arg7,arg8) \
1209 do { \
1210 volatile OrigFn _orig = (orig); \
1211 volatile unsigned long _argvec[9]; \
1212 volatile unsigned long _res; \
1213 _argvec[0] = (unsigned long)_orig.nraddr; \
1214 _argvec[1] = (unsigned long)(arg1); \
1215 _argvec[2] = (unsigned long)(arg2); \
1216 _argvec[3] = (unsigned long)(arg3); \
1217 _argvec[4] = (unsigned long)(arg4); \
1218 _argvec[5] = (unsigned long)(arg5); \
1219 _argvec[6] = (unsigned long)(arg6); \
1220 _argvec[7] = (unsigned long)(arg7); \
1221 _argvec[8] = (unsigned long)(arg8); \
1222 __asm__ volatile( \
1223 "pushq 64(%%rax)\n\t" \
1224 "pushq 56(%%rax)\n\t" \
1225 "movq 48(%%rax), %%r9\n\t" \
1226 "movq 40(%%rax), %%r8\n\t" \
1227 "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 \
1233 "addq $16, %%rsp\n" \
1234 : /*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_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1242 arg7,arg8,arg9) \
1243 do { \
1244 volatile OrigFn _orig = (orig); \
1245 volatile unsigned long _argvec[10]; \
1246 volatile unsigned long _res; \
1247 _argvec[0] = (unsigned long)_orig.nraddr; \
1248 _argvec[1] = (unsigned long)(arg1); \
1249 _argvec[2] = (unsigned long)(arg2); \
1250 _argvec[3] = (unsigned long)(arg3); \
1251 _argvec[4] = (unsigned long)(arg4); \
1252 _argvec[5] = (unsigned long)(arg5); \
1253 _argvec[6] = (unsigned long)(arg6); \
1254 _argvec[7] = (unsigned long)(arg7); \
1255 _argvec[8] = (unsigned long)(arg8); \
1256 _argvec[9] = (unsigned long)(arg9); \
1257 __asm__ volatile( \
1258 "pushq 72(%%rax)\n\t" \
1259 "pushq 64(%%rax)\n\t" \
1260 "pushq 56(%%rax)\n\t" \
1261 "movq 48(%%rax), %%r9\n\t" \
1262 "movq 40(%%rax), %%r8\n\t" \
1263 "movq 32(%%rax), %%rcx\n\t" \
1264 "movq 24(%%rax), %%rdx\n\t" \
1265 "movq 16(%%rax), %%rsi\n\t" \
1266 "movq 8(%%rax), %%rdi\n\t" \
1267 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1268 VALGRIND_CALL_NOREDIR_RAX \
1269 "addq $24, %%rsp\n" \
1270 : /*out*/ "=a" (_res) \
1271 : /*in*/ "a" (&_argvec[0]) \
1272 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1273 ); \
1274 lval = (__typeof__(lval)) _res; \
1275 } while (0)
1276
1277#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1278 arg7,arg8,arg9,arg10) \
1279 do { \
1280 volatile OrigFn _orig = (orig); \
1281 volatile unsigned long _argvec[11]; \
1282 volatile unsigned long _res; \
1283 _argvec[0] = (unsigned long)_orig.nraddr; \
1284 _argvec[1] = (unsigned long)(arg1); \
1285 _argvec[2] = (unsigned long)(arg2); \
1286 _argvec[3] = (unsigned long)(arg3); \
1287 _argvec[4] = (unsigned long)(arg4); \
1288 _argvec[5] = (unsigned long)(arg5); \
1289 _argvec[6] = (unsigned long)(arg6); \
1290 _argvec[7] = (unsigned long)(arg7); \
1291 _argvec[8] = (unsigned long)(arg8); \
1292 _argvec[9] = (unsigned long)(arg9); \
1293 _argvec[10] = (unsigned long)(arg10); \
1294 __asm__ volatile( \
1295 "pushq 80(%%rax)\n\t" \
1296 "pushq 72(%%rax)\n\t" \
1297 "pushq 64(%%rax)\n\t" \
1298 "pushq 56(%%rax)\n\t" \
1299 "movq 48(%%rax), %%r9\n\t" \
1300 "movq 40(%%rax), %%r8\n\t" \
1301 "movq 32(%%rax), %%rcx\n\t" \
1302 "movq 24(%%rax), %%rdx\n\t" \
1303 "movq 16(%%rax), %%rsi\n\t" \
1304 "movq 8(%%rax), %%rdi\n\t" \
1305 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1306 VALGRIND_CALL_NOREDIR_RAX \
1307 "addq $32, %%rsp\n" \
1308 : /*out*/ "=a" (_res) \
1309 : /*in*/ "a" (&_argvec[0]) \
1310 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1311 ); \
1312 lval = (__typeof__(lval)) _res; \
1313 } while (0)
1314
1315#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1316 arg7,arg8,arg9,arg10,arg11) \
1317 do { \
1318 volatile OrigFn _orig = (orig); \
1319 volatile unsigned long _argvec[12]; \
1320 volatile unsigned long _res; \
1321 _argvec[0] = (unsigned long)_orig.nraddr; \
1322 _argvec[1] = (unsigned long)(arg1); \
1323 _argvec[2] = (unsigned long)(arg2); \
1324 _argvec[3] = (unsigned long)(arg3); \
1325 _argvec[4] = (unsigned long)(arg4); \
1326 _argvec[5] = (unsigned long)(arg5); \
1327 _argvec[6] = (unsigned long)(arg6); \
1328 _argvec[7] = (unsigned long)(arg7); \
1329 _argvec[8] = (unsigned long)(arg8); \
1330 _argvec[9] = (unsigned long)(arg9); \
1331 _argvec[10] = (unsigned long)(arg10); \
1332 _argvec[11] = (unsigned long)(arg11); \
1333 __asm__ volatile( \
1334 "pushq 88(%%rax)\n\t" \
1335 "pushq 80(%%rax)\n\t" \
1336 "pushq 72(%%rax)\n\t" \
1337 "pushq 64(%%rax)\n\t" \
1338 "pushq 56(%%rax)\n\t" \
1339 "movq 48(%%rax), %%r9\n\t" \
1340 "movq 40(%%rax), %%r8\n\t" \
1341 "movq 32(%%rax), %%rcx\n\t" \
1342 "movq 24(%%rax), %%rdx\n\t" \
1343 "movq 16(%%rax), %%rsi\n\t" \
1344 "movq 8(%%rax), %%rdi\n\t" \
1345 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1346 VALGRIND_CALL_NOREDIR_RAX \
1347 "addq $40, %%rsp\n" \
1348 : /*out*/ "=a" (_res) \
1349 : /*in*/ "a" (&_argvec[0]) \
1350 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1351 ); \
1352 lval = (__typeof__(lval)) _res; \
1353 } while (0)
1354
1355#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1356 arg7,arg8,arg9,arg10,arg11,arg12) \
1357 do { \
1358 volatile OrigFn _orig = (orig); \
1359 volatile unsigned long _argvec[13]; \
1360 volatile unsigned long _res; \
1361 _argvec[0] = (unsigned long)_orig.nraddr; \
1362 _argvec[1] = (unsigned long)(arg1); \
1363 _argvec[2] = (unsigned long)(arg2); \
1364 _argvec[3] = (unsigned long)(arg3); \
1365 _argvec[4] = (unsigned long)(arg4); \
1366 _argvec[5] = (unsigned long)(arg5); \
1367 _argvec[6] = (unsigned long)(arg6); \
1368 _argvec[7] = (unsigned long)(arg7); \
1369 _argvec[8] = (unsigned long)(arg8); \
1370 _argvec[9] = (unsigned long)(arg9); \
1371 _argvec[10] = (unsigned long)(arg10); \
1372 _argvec[11] = (unsigned long)(arg11); \
1373 _argvec[12] = (unsigned long)(arg12); \
1374 __asm__ volatile( \
1375 "pushq 96(%%rax)\n\t" \
1376 "pushq 88(%%rax)\n\t" \
1377 "pushq 80(%%rax)\n\t" \
1378 "pushq 72(%%rax)\n\t" \
1379 "pushq 64(%%rax)\n\t" \
1380 "pushq 56(%%rax)\n\t" \
1381 "movq 48(%%rax), %%r9\n\t" \
1382 "movq 40(%%rax), %%r8\n\t" \
1383 "movq 32(%%rax), %%rcx\n\t" \
1384 "movq 24(%%rax), %%rdx\n\t" \
1385 "movq 16(%%rax), %%rsi\n\t" \
1386 "movq 8(%%rax), %%rdi\n\t" \
1387 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1388 VALGRIND_CALL_NOREDIR_RAX \
1389 "addq $48, %%rsp\n" \
1390 : /*out*/ "=a" (_res) \
1391 : /*in*/ "a" (&_argvec[0]) \
1392 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1393 ); \
1394 lval = (__typeof__(lval)) _res; \
1395 } while (0)
1396
sewardjf5c1a7f2006-10-17 01:32:48 +00001397#endif /* PLAT_amd64_linux */
sewardj0ec07f32006-01-12 12:32:32 +00001398
sewardjf5c1a7f2006-10-17 01:32:48 +00001399/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00001400
sewardjf5c1a7f2006-10-17 01:32:48 +00001401#if defined(PLAT_ppc32_linux)
sewardj0ec07f32006-01-12 12:32:32 +00001402
sewardjead61df2006-03-12 13:39:15 +00001403/* This is useful for finding out about the on-stack stuff:
1404
1405 extern int f9 ( int,int,int,int,int,int,int,int,int );
1406 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1407 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1408 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1409
1410 int g9 ( void ) {
1411 return f9(11,22,33,44,55,66,77,88,99);
1412 }
1413 int g10 ( void ) {
1414 return f10(11,22,33,44,55,66,77,88,99,110);
1415 }
1416 int g11 ( void ) {
1417 return f11(11,22,33,44,55,66,77,88,99,110,121);
1418 }
1419 int g12 ( void ) {
1420 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1421 }
1422*/
1423
sewardj0ec07f32006-01-12 12:32:32 +00001424/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1425
1426/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00001427#define __CALLER_SAVED_REGS \
1428 "lr", "ctr", "xer", \
1429 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1430 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1431 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00001432
sewardjead61df2006-03-12 13:39:15 +00001433/* These CALL_FN_ macros assume that on ppc32-linux,
1434 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00001435
sewardj38de0992006-01-20 16:46:34 +00001436#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001437 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001438 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001439 volatile unsigned long _argvec[1]; \
1440 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001441 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001442 __asm__ volatile( \
1443 "mr 11,%1\n\t" \
1444 "lwz 11,0(11)\n\t" /* target->r11 */ \
1445 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1446 "mr %0,3" \
1447 : /*out*/ "=r" (_res) \
1448 : /*in*/ "r" (&_argvec[0]) \
1449 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1450 ); \
1451 lval = (__typeof__(lval)) _res; \
1452 } while (0)
1453
sewardj38de0992006-01-20 16:46:34 +00001454#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001455 do { \
sewardj38de0992006-01-20 16:46:34 +00001456 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001457 volatile unsigned long _argvec[2]; \
1458 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001459 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001460 _argvec[1] = (unsigned long)arg1; \
1461 __asm__ volatile( \
1462 "mr 11,%1\n\t" \
1463 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1464 "lwz 11,0(11)\n\t" /* target->r11 */ \
1465 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1466 "mr %0,3" \
1467 : /*out*/ "=r" (_res) \
1468 : /*in*/ "r" (&_argvec[0]) \
1469 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1470 ); \
1471 lval = (__typeof__(lval)) _res; \
1472 } while (0)
1473
sewardj38de0992006-01-20 16:46:34 +00001474#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001475 do { \
sewardj38de0992006-01-20 16:46:34 +00001476 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001477 volatile unsigned long _argvec[3]; \
1478 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001479 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001480 _argvec[1] = (unsigned long)arg1; \
1481 _argvec[2] = (unsigned long)arg2; \
1482 __asm__ volatile( \
1483 "mr 11,%1\n\t" \
1484 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1485 "lwz 4,8(11)\n\t" \
1486 "lwz 11,0(11)\n\t" /* target->r11 */ \
1487 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1488 "mr %0,3" \
1489 : /*out*/ "=r" (_res) \
1490 : /*in*/ "r" (&_argvec[0]) \
1491 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1492 ); \
1493 lval = (__typeof__(lval)) _res; \
1494 } while (0)
1495
sewardjead61df2006-03-12 13:39:15 +00001496#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1497 do { \
1498 volatile OrigFn _orig = (orig); \
1499 volatile unsigned long _argvec[4]; \
1500 volatile unsigned long _res; \
1501 _argvec[0] = (unsigned long)_orig.nraddr; \
1502 _argvec[1] = (unsigned long)arg1; \
1503 _argvec[2] = (unsigned long)arg2; \
1504 _argvec[3] = (unsigned long)arg3; \
1505 __asm__ volatile( \
1506 "mr 11,%1\n\t" \
1507 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1508 "lwz 4,8(11)\n\t" \
1509 "lwz 5,12(11)\n\t" \
1510 "lwz 11,0(11)\n\t" /* target->r11 */ \
1511 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1512 "mr %0,3" \
1513 : /*out*/ "=r" (_res) \
1514 : /*in*/ "r" (&_argvec[0]) \
1515 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1516 ); \
1517 lval = (__typeof__(lval)) _res; \
1518 } while (0)
1519
1520#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1521 do { \
1522 volatile OrigFn _orig = (orig); \
1523 volatile unsigned long _argvec[5]; \
1524 volatile unsigned long _res; \
1525 _argvec[0] = (unsigned long)_orig.nraddr; \
1526 _argvec[1] = (unsigned long)arg1; \
1527 _argvec[2] = (unsigned long)arg2; \
1528 _argvec[3] = (unsigned long)arg3; \
1529 _argvec[4] = (unsigned long)arg4; \
1530 __asm__ volatile( \
1531 "mr 11,%1\n\t" \
1532 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1533 "lwz 4,8(11)\n\t" \
1534 "lwz 5,12(11)\n\t" \
1535 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1536 "lwz 11,0(11)\n\t" /* target->r11 */ \
1537 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1538 "mr %0,3" \
1539 : /*out*/ "=r" (_res) \
1540 : /*in*/ "r" (&_argvec[0]) \
1541 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1542 ); \
1543 lval = (__typeof__(lval)) _res; \
1544 } while (0)
1545
1546#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1547 do { \
1548 volatile OrigFn _orig = (orig); \
1549 volatile unsigned long _argvec[6]; \
1550 volatile unsigned long _res; \
1551 _argvec[0] = (unsigned long)_orig.nraddr; \
1552 _argvec[1] = (unsigned long)arg1; \
1553 _argvec[2] = (unsigned long)arg2; \
1554 _argvec[3] = (unsigned long)arg3; \
1555 _argvec[4] = (unsigned long)arg4; \
1556 _argvec[5] = (unsigned long)arg5; \
1557 __asm__ volatile( \
1558 "mr 11,%1\n\t" \
1559 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1560 "lwz 4,8(11)\n\t" \
1561 "lwz 5,12(11)\n\t" \
1562 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1563 "lwz 7,20(11)\n\t" \
1564 "lwz 11,0(11)\n\t" /* target->r11 */ \
1565 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1566 "mr %0,3" \
1567 : /*out*/ "=r" (_res) \
1568 : /*in*/ "r" (&_argvec[0]) \
1569 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1570 ); \
1571 lval = (__typeof__(lval)) _res; \
1572 } while (0)
1573
1574#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1575 do { \
1576 volatile OrigFn _orig = (orig); \
1577 volatile unsigned long _argvec[7]; \
1578 volatile unsigned long _res; \
1579 _argvec[0] = (unsigned long)_orig.nraddr; \
1580 _argvec[1] = (unsigned long)arg1; \
1581 _argvec[2] = (unsigned long)arg2; \
1582 _argvec[3] = (unsigned long)arg3; \
1583 _argvec[4] = (unsigned long)arg4; \
1584 _argvec[5] = (unsigned long)arg5; \
1585 _argvec[6] = (unsigned long)arg6; \
1586 __asm__ volatile( \
1587 "mr 11,%1\n\t" \
1588 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1589 "lwz 4,8(11)\n\t" \
1590 "lwz 5,12(11)\n\t" \
1591 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1592 "lwz 7,20(11)\n\t" \
1593 "lwz 8,24(11)\n\t" \
1594 "lwz 11,0(11)\n\t" /* target->r11 */ \
1595 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1596 "mr %0,3" \
1597 : /*out*/ "=r" (_res) \
1598 : /*in*/ "r" (&_argvec[0]) \
1599 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1600 ); \
1601 lval = (__typeof__(lval)) _res; \
1602 } while (0)
1603
1604#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1605 arg7) \
1606 do { \
1607 volatile OrigFn _orig = (orig); \
1608 volatile unsigned long _argvec[8]; \
1609 volatile unsigned long _res; \
1610 _argvec[0] = (unsigned long)_orig.nraddr; \
1611 _argvec[1] = (unsigned long)arg1; \
1612 _argvec[2] = (unsigned long)arg2; \
1613 _argvec[3] = (unsigned long)arg3; \
1614 _argvec[4] = (unsigned long)arg4; \
1615 _argvec[5] = (unsigned long)arg5; \
1616 _argvec[6] = (unsigned long)arg6; \
1617 _argvec[7] = (unsigned long)arg7; \
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 5,12(11)\n\t" \
1623 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1624 "lwz 7,20(11)\n\t" \
1625 "lwz 8,24(11)\n\t" \
1626 "lwz 9,28(11)\n\t" \
1627 "lwz 11,0(11)\n\t" /* target->r11 */ \
1628 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1629 "mr %0,3" \
1630 : /*out*/ "=r" (_res) \
1631 : /*in*/ "r" (&_argvec[0]) \
1632 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1633 ); \
1634 lval = (__typeof__(lval)) _res; \
1635 } while (0)
1636
1637#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1638 arg7,arg8) \
1639 do { \
1640 volatile OrigFn _orig = (orig); \
1641 volatile unsigned long _argvec[9]; \
1642 volatile unsigned long _res; \
1643 _argvec[0] = (unsigned long)_orig.nraddr; \
1644 _argvec[1] = (unsigned long)arg1; \
1645 _argvec[2] = (unsigned long)arg2; \
1646 _argvec[3] = (unsigned long)arg3; \
1647 _argvec[4] = (unsigned long)arg4; \
1648 _argvec[5] = (unsigned long)arg5; \
1649 _argvec[6] = (unsigned long)arg6; \
1650 _argvec[7] = (unsigned long)arg7; \
1651 _argvec[8] = (unsigned long)arg8; \
1652 __asm__ volatile( \
1653 "mr 11,%1\n\t" \
1654 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1655 "lwz 4,8(11)\n\t" \
1656 "lwz 5,12(11)\n\t" \
1657 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1658 "lwz 7,20(11)\n\t" \
1659 "lwz 8,24(11)\n\t" \
1660 "lwz 9,28(11)\n\t" \
1661 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1662 "lwz 11,0(11)\n\t" /* target->r11 */ \
1663 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1664 "mr %0,3" \
1665 : /*out*/ "=r" (_res) \
1666 : /*in*/ "r" (&_argvec[0]) \
1667 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1668 ); \
1669 lval = (__typeof__(lval)) _res; \
1670 } while (0)
1671
1672#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1673 arg7,arg8,arg9) \
1674 do { \
1675 volatile OrigFn _orig = (orig); \
1676 volatile unsigned long _argvec[10]; \
1677 volatile unsigned long _res; \
1678 _argvec[0] = (unsigned long)_orig.nraddr; \
1679 _argvec[1] = (unsigned long)arg1; \
1680 _argvec[2] = (unsigned long)arg2; \
1681 _argvec[3] = (unsigned long)arg3; \
1682 _argvec[4] = (unsigned long)arg4; \
1683 _argvec[5] = (unsigned long)arg5; \
1684 _argvec[6] = (unsigned long)arg6; \
1685 _argvec[7] = (unsigned long)arg7; \
1686 _argvec[8] = (unsigned long)arg8; \
1687 _argvec[9] = (unsigned long)arg9; \
1688 __asm__ volatile( \
1689 "mr 11,%1\n\t" \
1690 "addi 1,1,-16\n\t" \
1691 /* arg9 */ \
1692 "lwz 3,36(11)\n\t" \
1693 "stw 3,8(1)\n\t" \
1694 /* args1-8 */ \
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 8,24(11)\n\t" \
1701 "lwz 9,28(11)\n\t" \
1702 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1703 "lwz 11,0(11)\n\t" /* target->r11 */ \
1704 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1705 "addi 1,1,16\n\t" \
1706 "mr %0,3" \
1707 : /*out*/ "=r" (_res) \
1708 : /*in*/ "r" (&_argvec[0]) \
1709 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1710 ); \
1711 lval = (__typeof__(lval)) _res; \
1712 } while (0)
1713
1714#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1715 arg7,arg8,arg9,arg10) \
1716 do { \
1717 volatile OrigFn _orig = (orig); \
1718 volatile unsigned long _argvec[11]; \
1719 volatile unsigned long _res; \
1720 _argvec[0] = (unsigned long)_orig.nraddr; \
1721 _argvec[1] = (unsigned long)arg1; \
1722 _argvec[2] = (unsigned long)arg2; \
1723 _argvec[3] = (unsigned long)arg3; \
1724 _argvec[4] = (unsigned long)arg4; \
1725 _argvec[5] = (unsigned long)arg5; \
1726 _argvec[6] = (unsigned long)arg6; \
1727 _argvec[7] = (unsigned long)arg7; \
1728 _argvec[8] = (unsigned long)arg8; \
1729 _argvec[9] = (unsigned long)arg9; \
1730 _argvec[10] = (unsigned long)arg10; \
1731 __asm__ volatile( \
1732 "mr 11,%1\n\t" \
1733 "addi 1,1,-16\n\t" \
1734 /* arg10 */ \
1735 "lwz 3,40(11)\n\t" \
1736 "stw 3,12(1)\n\t" \
1737 /* arg9 */ \
1738 "lwz 3,36(11)\n\t" \
1739 "stw 3,8(1)\n\t" \
1740 /* args1-8 */ \
1741 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1742 "lwz 4,8(11)\n\t" \
1743 "lwz 5,12(11)\n\t" \
1744 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1745 "lwz 7,20(11)\n\t" \
1746 "lwz 8,24(11)\n\t" \
1747 "lwz 9,28(11)\n\t" \
1748 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1749 "lwz 11,0(11)\n\t" /* target->r11 */ \
1750 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1751 "addi 1,1,16\n\t" \
1752 "mr %0,3" \
1753 : /*out*/ "=r" (_res) \
1754 : /*in*/ "r" (&_argvec[0]) \
1755 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1756 ); \
1757 lval = (__typeof__(lval)) _res; \
1758 } while (0)
1759
1760#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1761 arg7,arg8,arg9,arg10,arg11) \
1762 do { \
1763 volatile OrigFn _orig = (orig); \
1764 volatile unsigned long _argvec[12]; \
1765 volatile unsigned long _res; \
1766 _argvec[0] = (unsigned long)_orig.nraddr; \
1767 _argvec[1] = (unsigned long)arg1; \
1768 _argvec[2] = (unsigned long)arg2; \
1769 _argvec[3] = (unsigned long)arg3; \
1770 _argvec[4] = (unsigned long)arg4; \
1771 _argvec[5] = (unsigned long)arg5; \
1772 _argvec[6] = (unsigned long)arg6; \
1773 _argvec[7] = (unsigned long)arg7; \
1774 _argvec[8] = (unsigned long)arg8; \
1775 _argvec[9] = (unsigned long)arg9; \
1776 _argvec[10] = (unsigned long)arg10; \
1777 _argvec[11] = (unsigned long)arg11; \
1778 __asm__ volatile( \
1779 "mr 11,%1\n\t" \
1780 "addi 1,1,-32\n\t" \
1781 /* arg11 */ \
1782 "lwz 3,44(11)\n\t" \
1783 "stw 3,16(1)\n\t" \
1784 /* arg10 */ \
1785 "lwz 3,40(11)\n\t" \
1786 "stw 3,12(1)\n\t" \
1787 /* arg9 */ \
1788 "lwz 3,36(11)\n\t" \
1789 "stw 3,8(1)\n\t" \
1790 /* args1-8 */ \
1791 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1792 "lwz 4,8(11)\n\t" \
1793 "lwz 5,12(11)\n\t" \
1794 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1795 "lwz 7,20(11)\n\t" \
1796 "lwz 8,24(11)\n\t" \
1797 "lwz 9,28(11)\n\t" \
1798 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1799 "lwz 11,0(11)\n\t" /* target->r11 */ \
1800 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1801 "addi 1,1,32\n\t" \
1802 "mr %0,3" \
1803 : /*out*/ "=r" (_res) \
1804 : /*in*/ "r" (&_argvec[0]) \
1805 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1806 ); \
1807 lval = (__typeof__(lval)) _res; \
1808 } while (0)
1809
1810#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1811 arg7,arg8,arg9,arg10,arg11,arg12) \
1812 do { \
1813 volatile OrigFn _orig = (orig); \
1814 volatile unsigned long _argvec[13]; \
1815 volatile unsigned long _res; \
1816 _argvec[0] = (unsigned long)_orig.nraddr; \
1817 _argvec[1] = (unsigned long)arg1; \
1818 _argvec[2] = (unsigned long)arg2; \
1819 _argvec[3] = (unsigned long)arg3; \
1820 _argvec[4] = (unsigned long)arg4; \
1821 _argvec[5] = (unsigned long)arg5; \
1822 _argvec[6] = (unsigned long)arg6; \
1823 _argvec[7] = (unsigned long)arg7; \
1824 _argvec[8] = (unsigned long)arg8; \
1825 _argvec[9] = (unsigned long)arg9; \
1826 _argvec[10] = (unsigned long)arg10; \
1827 _argvec[11] = (unsigned long)arg11; \
1828 _argvec[12] = (unsigned long)arg12; \
1829 __asm__ volatile( \
1830 "mr 11,%1\n\t" \
1831 "addi 1,1,-32\n\t" \
1832 /* arg12 */ \
1833 "lwz 3,48(11)\n\t" \
1834 "stw 3,20(1)\n\t" \
1835 /* arg11 */ \
1836 "lwz 3,44(11)\n\t" \
1837 "stw 3,16(1)\n\t" \
1838 /* arg10 */ \
1839 "lwz 3,40(11)\n\t" \
1840 "stw 3,12(1)\n\t" \
1841 /* arg9 */ \
1842 "lwz 3,36(11)\n\t" \
1843 "stw 3,8(1)\n\t" \
1844 /* args1-8 */ \
1845 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1846 "lwz 4,8(11)\n\t" \
1847 "lwz 5,12(11)\n\t" \
1848 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1849 "lwz 7,20(11)\n\t" \
1850 "lwz 8,24(11)\n\t" \
1851 "lwz 9,28(11)\n\t" \
1852 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1853 "lwz 11,0(11)\n\t" /* target->r11 */ \
1854 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1855 "addi 1,1,32\n\t" \
1856 "mr %0,3" \
1857 : /*out*/ "=r" (_res) \
1858 : /*in*/ "r" (&_argvec[0]) \
1859 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1860 ); \
1861 lval = (__typeof__(lval)) _res; \
1862 } while (0)
1863
sewardjf5c1a7f2006-10-17 01:32:48 +00001864#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +00001865
sewardjf5c1a7f2006-10-17 01:32:48 +00001866/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00001867
sewardjf5c1a7f2006-10-17 01:32:48 +00001868#if defined(PLAT_ppc64_linux)
sewardj9734b202006-01-17 01:49:37 +00001869
1870/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1871
1872/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00001873#define __CALLER_SAVED_REGS \
1874 "lr", "ctr", "xer", \
1875 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1876 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1877 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00001878
1879/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
1880 long) == 8. */
1881
sewardjd68ac3e2006-01-20 14:31:57 +00001882#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00001883 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001884 volatile OrigFn _orig = (orig); \
1885 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00001886 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001887 /* _argvec[0] holds current r2 across the call */ \
1888 _argvec[1] = (unsigned long)_orig.r2; \
1889 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00001890 __asm__ volatile( \
1891 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001892 "std 2,-16(11)\n\t" /* save tocptr */ \
1893 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1894 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00001895 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1896 "mr 11,%1\n\t" \
1897 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001898 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00001899 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00001900 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00001901 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1902 ); \
1903 lval = (__typeof__(lval)) _res; \
1904 } while (0)
1905
sewardjd68ac3e2006-01-20 14:31:57 +00001906#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00001907 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001908 volatile OrigFn _orig = (orig); \
1909 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00001910 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001911 /* _argvec[0] holds current r2 across the call */ \
1912 _argvec[1] = (unsigned long)_orig.r2; \
1913 _argvec[2] = (unsigned long)_orig.nraddr; \
1914 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00001915 __asm__ volatile( \
1916 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001917 "std 2,-16(11)\n\t" /* save tocptr */ \
1918 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1919 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1920 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00001921 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1922 "mr 11,%1\n\t" \
1923 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001924 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00001925 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00001926 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00001927 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1928 ); \
1929 lval = (__typeof__(lval)) _res; \
1930 } while (0)
1931
sewardjd68ac3e2006-01-20 14:31:57 +00001932#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00001933 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001934 volatile OrigFn _orig = (orig); \
1935 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00001936 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001937 /* _argvec[0] holds current r2 across the call */ \
1938 _argvec[1] = (unsigned long)_orig.r2; \
1939 _argvec[2] = (unsigned long)_orig.nraddr; \
1940 _argvec[2+1] = (unsigned long)arg1; \
1941 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00001942 __asm__ volatile( \
1943 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001944 "std 2,-16(11)\n\t" /* save tocptr */ \
1945 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1946 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00001947 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00001948 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00001949 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1950 "mr 11,%1\n\t" \
1951 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001952 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00001953 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00001954 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00001955 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1956 ); \
1957 lval = (__typeof__(lval)) _res; \
1958 } while (0)
1959
sewardjcd636392006-03-12 16:48:14 +00001960#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1961 do { \
1962 volatile OrigFn _orig = (orig); \
1963 volatile unsigned long _argvec[3+3]; \
1964 volatile unsigned long _res; \
1965 /* _argvec[0] holds current r2 across the call */ \
1966 _argvec[1] = (unsigned long)_orig.r2; \
1967 _argvec[2] = (unsigned long)_orig.nraddr; \
1968 _argvec[2+1] = (unsigned long)arg1; \
1969 _argvec[2+2] = (unsigned long)arg2; \
1970 _argvec[2+3] = (unsigned long)arg3; \
1971 __asm__ volatile( \
1972 "mr 11,%1\n\t" \
1973 "std 2,-16(11)\n\t" /* save tocptr */ \
1974 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1975 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1976 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1977 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1978 "ld 11, 0(11)\n\t" /* target->r11 */ \
1979 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1980 "mr 11,%1\n\t" \
1981 "mr %0,3\n\t" \
1982 "ld 2,-16(11)" /* restore tocptr */ \
1983 : /*out*/ "=r" (_res) \
1984 : /*in*/ "r" (&_argvec[2]) \
1985 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1986 ); \
1987 lval = (__typeof__(lval)) _res; \
1988 } while (0)
1989
1990#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1991 do { \
1992 volatile OrigFn _orig = (orig); \
1993 volatile unsigned long _argvec[3+4]; \
1994 volatile unsigned long _res; \
1995 /* _argvec[0] holds current r2 across the call */ \
1996 _argvec[1] = (unsigned long)_orig.r2; \
1997 _argvec[2] = (unsigned long)_orig.nraddr; \
1998 _argvec[2+1] = (unsigned long)arg1; \
1999 _argvec[2+2] = (unsigned long)arg2; \
2000 _argvec[2+3] = (unsigned long)arg3; \
2001 _argvec[2+4] = (unsigned long)arg4; \
2002 __asm__ volatile( \
2003 "mr 11,%1\n\t" \
2004 "std 2,-16(11)\n\t" /* save tocptr */ \
2005 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2006 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2007 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2008 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2009 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2010 "ld 11, 0(11)\n\t" /* target->r11 */ \
2011 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2012 "mr 11,%1\n\t" \
2013 "mr %0,3\n\t" \
2014 "ld 2,-16(11)" /* restore tocptr */ \
2015 : /*out*/ "=r" (_res) \
2016 : /*in*/ "r" (&_argvec[2]) \
2017 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2018 ); \
2019 lval = (__typeof__(lval)) _res; \
2020 } while (0)
2021
2022#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2023 do { \
2024 volatile OrigFn _orig = (orig); \
2025 volatile unsigned long _argvec[3+5]; \
2026 volatile unsigned long _res; \
2027 /* _argvec[0] holds current r2 across the call */ \
2028 _argvec[1] = (unsigned long)_orig.r2; \
2029 _argvec[2] = (unsigned long)_orig.nraddr; \
2030 _argvec[2+1] = (unsigned long)arg1; \
2031 _argvec[2+2] = (unsigned long)arg2; \
2032 _argvec[2+3] = (unsigned long)arg3; \
2033 _argvec[2+4] = (unsigned long)arg4; \
2034 _argvec[2+5] = (unsigned long)arg5; \
2035 __asm__ volatile( \
2036 "mr 11,%1\n\t" \
2037 "std 2,-16(11)\n\t" /* save tocptr */ \
2038 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2039 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2040 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2041 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2042 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2043 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2044 "ld 11, 0(11)\n\t" /* target->r11 */ \
2045 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2046 "mr 11,%1\n\t" \
2047 "mr %0,3\n\t" \
2048 "ld 2,-16(11)" /* restore tocptr */ \
2049 : /*out*/ "=r" (_res) \
2050 : /*in*/ "r" (&_argvec[2]) \
2051 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2052 ); \
2053 lval = (__typeof__(lval)) _res; \
2054 } while (0)
2055
2056#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2057 do { \
2058 volatile OrigFn _orig = (orig); \
2059 volatile unsigned long _argvec[3+6]; \
2060 volatile unsigned long _res; \
2061 /* _argvec[0] holds current r2 across the call */ \
2062 _argvec[1] = (unsigned long)_orig.r2; \
2063 _argvec[2] = (unsigned long)_orig.nraddr; \
2064 _argvec[2+1] = (unsigned long)arg1; \
2065 _argvec[2+2] = (unsigned long)arg2; \
2066 _argvec[2+3] = (unsigned long)arg3; \
2067 _argvec[2+4] = (unsigned long)arg4; \
2068 _argvec[2+5] = (unsigned long)arg5; \
2069 _argvec[2+6] = (unsigned long)arg6; \
2070 __asm__ volatile( \
2071 "mr 11,%1\n\t" \
2072 "std 2,-16(11)\n\t" /* save tocptr */ \
2073 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2074 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2075 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2076 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2077 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2078 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2079 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2080 "ld 11, 0(11)\n\t" /* target->r11 */ \
2081 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2082 "mr 11,%1\n\t" \
2083 "mr %0,3\n\t" \
2084 "ld 2,-16(11)" /* restore tocptr */ \
2085 : /*out*/ "=r" (_res) \
2086 : /*in*/ "r" (&_argvec[2]) \
2087 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2088 ); \
2089 lval = (__typeof__(lval)) _res; \
2090 } while (0)
2091
2092#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2093 arg7) \
2094 do { \
2095 volatile OrigFn _orig = (orig); \
2096 volatile unsigned long _argvec[3+7]; \
2097 volatile unsigned long _res; \
2098 /* _argvec[0] holds current r2 across the call */ \
2099 _argvec[1] = (unsigned long)_orig.r2; \
2100 _argvec[2] = (unsigned long)_orig.nraddr; \
2101 _argvec[2+1] = (unsigned long)arg1; \
2102 _argvec[2+2] = (unsigned long)arg2; \
2103 _argvec[2+3] = (unsigned long)arg3; \
2104 _argvec[2+4] = (unsigned long)arg4; \
2105 _argvec[2+5] = (unsigned long)arg5; \
2106 _argvec[2+6] = (unsigned long)arg6; \
2107 _argvec[2+7] = (unsigned long)arg7; \
2108 __asm__ volatile( \
2109 "mr 11,%1\n\t" \
2110 "std 2,-16(11)\n\t" /* save tocptr */ \
2111 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2112 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2113 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2114 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2115 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2116 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2117 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2118 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2119 "ld 11, 0(11)\n\t" /* target->r11 */ \
2120 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2121 "mr 11,%1\n\t" \
2122 "mr %0,3\n\t" \
2123 "ld 2,-16(11)" /* restore tocptr */ \
2124 : /*out*/ "=r" (_res) \
2125 : /*in*/ "r" (&_argvec[2]) \
2126 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2127 ); \
2128 lval = (__typeof__(lval)) _res; \
2129 } while (0)
2130
2131#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2132 arg7,arg8) \
2133 do { \
2134 volatile OrigFn _orig = (orig); \
2135 volatile unsigned long _argvec[3+8]; \
2136 volatile unsigned long _res; \
2137 /* _argvec[0] holds current r2 across the call */ \
2138 _argvec[1] = (unsigned long)_orig.r2; \
2139 _argvec[2] = (unsigned long)_orig.nraddr; \
2140 _argvec[2+1] = (unsigned long)arg1; \
2141 _argvec[2+2] = (unsigned long)arg2; \
2142 _argvec[2+3] = (unsigned long)arg3; \
2143 _argvec[2+4] = (unsigned long)arg4; \
2144 _argvec[2+5] = (unsigned long)arg5; \
2145 _argvec[2+6] = (unsigned long)arg6; \
2146 _argvec[2+7] = (unsigned long)arg7; \
2147 _argvec[2+8] = (unsigned long)arg8; \
2148 __asm__ volatile( \
2149 "mr 11,%1\n\t" \
2150 "std 2,-16(11)\n\t" /* save tocptr */ \
2151 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2152 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2153 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2154 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2155 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2156 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2157 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2158 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2159 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2160 "ld 11, 0(11)\n\t" /* target->r11 */ \
2161 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2162 "mr 11,%1\n\t" \
2163 "mr %0,3\n\t" \
2164 "ld 2,-16(11)" /* restore tocptr */ \
2165 : /*out*/ "=r" (_res) \
2166 : /*in*/ "r" (&_argvec[2]) \
2167 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2168 ); \
2169 lval = (__typeof__(lval)) _res; \
2170 } while (0)
2171
2172#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2173 arg7,arg8,arg9) \
2174 do { \
2175 volatile OrigFn _orig = (orig); \
2176 volatile unsigned long _argvec[3+9]; \
2177 volatile unsigned long _res; \
2178 /* _argvec[0] holds current r2 across the call */ \
2179 _argvec[1] = (unsigned long)_orig.r2; \
2180 _argvec[2] = (unsigned long)_orig.nraddr; \
2181 _argvec[2+1] = (unsigned long)arg1; \
2182 _argvec[2+2] = (unsigned long)arg2; \
2183 _argvec[2+3] = (unsigned long)arg3; \
2184 _argvec[2+4] = (unsigned long)arg4; \
2185 _argvec[2+5] = (unsigned long)arg5; \
2186 _argvec[2+6] = (unsigned long)arg6; \
2187 _argvec[2+7] = (unsigned long)arg7; \
2188 _argvec[2+8] = (unsigned long)arg8; \
2189 _argvec[2+9] = (unsigned long)arg9; \
2190 __asm__ volatile( \
2191 "mr 11,%1\n\t" \
2192 "std 2,-16(11)\n\t" /* save tocptr */ \
2193 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2194 "addi 1,1,-128\n\t" /* expand stack frame */ \
2195 /* arg9 */ \
2196 "ld 3,72(11)\n\t" \
2197 "std 3,112(1)\n\t" \
2198 /* args1-8 */ \
2199 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2200 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2201 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2202 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2203 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2204 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2205 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2206 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2207 "ld 11, 0(11)\n\t" /* target->r11 */ \
2208 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2209 "mr 11,%1\n\t" \
2210 "mr %0,3\n\t" \
2211 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2212 "addi 1,1,128" /* restore frame */ \
2213 : /*out*/ "=r" (_res) \
2214 : /*in*/ "r" (&_argvec[2]) \
2215 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2216 ); \
2217 lval = (__typeof__(lval)) _res; \
2218 } while (0)
2219
2220#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2221 arg7,arg8,arg9,arg10) \
2222 do { \
2223 volatile OrigFn _orig = (orig); \
2224 volatile unsigned long _argvec[3+10]; \
2225 volatile unsigned long _res; \
2226 /* _argvec[0] holds current r2 across the call */ \
2227 _argvec[1] = (unsigned long)_orig.r2; \
2228 _argvec[2] = (unsigned long)_orig.nraddr; \
2229 _argvec[2+1] = (unsigned long)arg1; \
2230 _argvec[2+2] = (unsigned long)arg2; \
2231 _argvec[2+3] = (unsigned long)arg3; \
2232 _argvec[2+4] = (unsigned long)arg4; \
2233 _argvec[2+5] = (unsigned long)arg5; \
2234 _argvec[2+6] = (unsigned long)arg6; \
2235 _argvec[2+7] = (unsigned long)arg7; \
2236 _argvec[2+8] = (unsigned long)arg8; \
2237 _argvec[2+9] = (unsigned long)arg9; \
2238 _argvec[2+10] = (unsigned long)arg10; \
2239 __asm__ volatile( \
2240 "mr 11,%1\n\t" \
2241 "std 2,-16(11)\n\t" /* save tocptr */ \
2242 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2243 "addi 1,1,-128\n\t" /* expand stack frame */ \
2244 /* arg10 */ \
2245 "ld 3,80(11)\n\t" \
2246 "std 3,120(1)\n\t" \
2247 /* arg9 */ \
2248 "ld 3,72(11)\n\t" \
2249 "std 3,112(1)\n\t" \
2250 /* args1-8 */ \
2251 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2252 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2253 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2254 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2255 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2256 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2257 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2258 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2259 "ld 11, 0(11)\n\t" /* target->r11 */ \
2260 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2261 "mr 11,%1\n\t" \
2262 "mr %0,3\n\t" \
2263 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2264 "addi 1,1,128" /* restore frame */ \
2265 : /*out*/ "=r" (_res) \
2266 : /*in*/ "r" (&_argvec[2]) \
2267 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2268 ); \
2269 lval = (__typeof__(lval)) _res; \
2270 } while (0)
2271
2272#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2273 arg7,arg8,arg9,arg10,arg11) \
2274 do { \
2275 volatile OrigFn _orig = (orig); \
2276 volatile unsigned long _argvec[3+11]; \
2277 volatile unsigned long _res; \
2278 /* _argvec[0] holds current r2 across the call */ \
2279 _argvec[1] = (unsigned long)_orig.r2; \
2280 _argvec[2] = (unsigned long)_orig.nraddr; \
2281 _argvec[2+1] = (unsigned long)arg1; \
2282 _argvec[2+2] = (unsigned long)arg2; \
2283 _argvec[2+3] = (unsigned long)arg3; \
2284 _argvec[2+4] = (unsigned long)arg4; \
2285 _argvec[2+5] = (unsigned long)arg5; \
2286 _argvec[2+6] = (unsigned long)arg6; \
2287 _argvec[2+7] = (unsigned long)arg7; \
2288 _argvec[2+8] = (unsigned long)arg8; \
2289 _argvec[2+9] = (unsigned long)arg9; \
2290 _argvec[2+10] = (unsigned long)arg10; \
2291 _argvec[2+11] = (unsigned long)arg11; \
2292 __asm__ volatile( \
2293 "mr 11,%1\n\t" \
2294 "std 2,-16(11)\n\t" /* save tocptr */ \
2295 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2296 "addi 1,1,-144\n\t" /* expand stack frame */ \
2297 /* arg11 */ \
2298 "ld 3,88(11)\n\t" \
2299 "std 3,128(1)\n\t" \
2300 /* arg10 */ \
2301 "ld 3,80(11)\n\t" \
2302 "std 3,120(1)\n\t" \
2303 /* arg9 */ \
2304 "ld 3,72(11)\n\t" \
2305 "std 3,112(1)\n\t" \
2306 /* args1-8 */ \
2307 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2308 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2309 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2310 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2311 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2312 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2313 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2314 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2315 "ld 11, 0(11)\n\t" /* target->r11 */ \
2316 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2317 "mr 11,%1\n\t" \
2318 "mr %0,3\n\t" \
2319 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2320 "addi 1,1,144" /* restore frame */ \
2321 : /*out*/ "=r" (_res) \
2322 : /*in*/ "r" (&_argvec[2]) \
2323 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2324 ); \
2325 lval = (__typeof__(lval)) _res; \
2326 } while (0)
2327
2328#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2329 arg7,arg8,arg9,arg10,arg11,arg12) \
2330 do { \
2331 volatile OrigFn _orig = (orig); \
2332 volatile unsigned long _argvec[3+12]; \
2333 volatile unsigned long _res; \
2334 /* _argvec[0] holds current r2 across the call */ \
2335 _argvec[1] = (unsigned long)_orig.r2; \
2336 _argvec[2] = (unsigned long)_orig.nraddr; \
2337 _argvec[2+1] = (unsigned long)arg1; \
2338 _argvec[2+2] = (unsigned long)arg2; \
2339 _argvec[2+3] = (unsigned long)arg3; \
2340 _argvec[2+4] = (unsigned long)arg4; \
2341 _argvec[2+5] = (unsigned long)arg5; \
2342 _argvec[2+6] = (unsigned long)arg6; \
2343 _argvec[2+7] = (unsigned long)arg7; \
2344 _argvec[2+8] = (unsigned long)arg8; \
2345 _argvec[2+9] = (unsigned long)arg9; \
2346 _argvec[2+10] = (unsigned long)arg10; \
2347 _argvec[2+11] = (unsigned long)arg11; \
2348 _argvec[2+12] = (unsigned long)arg12; \
2349 __asm__ volatile( \
2350 "mr 11,%1\n\t" \
2351 "std 2,-16(11)\n\t" /* save tocptr */ \
2352 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2353 "addi 1,1,-144\n\t" /* expand stack frame */ \
2354 /* arg12 */ \
2355 "ld 3,96(11)\n\t" \
2356 "std 3,136(1)\n\t" \
2357 /* arg11 */ \
2358 "ld 3,88(11)\n\t" \
2359 "std 3,128(1)\n\t" \
2360 /* arg10 */ \
2361 "ld 3,80(11)\n\t" \
2362 "std 3,120(1)\n\t" \
2363 /* arg9 */ \
2364 "ld 3,72(11)\n\t" \
2365 "std 3,112(1)\n\t" \
2366 /* args1-8 */ \
2367 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2368 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2369 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2370 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2371 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2372 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2373 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2374 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2375 "ld 11, 0(11)\n\t" /* target->r11 */ \
2376 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2377 "mr 11,%1\n\t" \
2378 "mr %0,3\n\t" \
2379 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2380 "addi 1,1,144" /* restore frame */ \
2381 : /*out*/ "=r" (_res) \
2382 : /*in*/ "r" (&_argvec[2]) \
2383 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2384 ); \
2385 lval = (__typeof__(lval)) _res; \
2386 } while (0)
2387
sewardjf5c1a7f2006-10-17 01:32:48 +00002388#endif /* PLAT_ppc64_linux */
2389
2390/* ------------------------ ppc32-aix5 ------------------------- */
2391
2392#if defined(PLAT_ppc32_aix5)
2393
2394/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2395
2396/* These regs are trashed by the hidden call. */
2397#define __CALLER_SAVED_REGS \
2398 "lr", "ctr", "xer", \
2399 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2400 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2401 "r11", "r12", "r13"
2402
2403/* Expand the stack frame, copying enough info that unwinding
2404 still works. Trashes r3. */
2405
2406#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
2407 "addi 1,1,-" #_n_fr "\n\t" \
2408 "lwz 3," #_n_fr "(1)\n\t" \
2409 "stw 3,0(1)\n\t"
2410
2411#define VG_CONTRACT_FRAME_BY(_n_fr) \
2412 "addi 1,1," #_n_fr "\n\t"
2413
2414/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
2415 long) == 4. */
2416
2417#define CALL_FN_W_v(lval, orig) \
2418 do { \
2419 volatile OrigFn _orig = (orig); \
2420 volatile unsigned long _argvec[3+0]; \
2421 volatile unsigned long _res; \
2422 /* _argvec[0] holds current r2 across the call */ \
2423 _argvec[1] = (unsigned long)_orig.r2; \
2424 _argvec[2] = (unsigned long)_orig.nraddr; \
2425 __asm__ volatile( \
2426 "mr 11,%1\n\t" \
2427 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2428 "stw 2,-8(11)\n\t" /* save tocptr */ \
2429 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2430 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2431 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2432 "mr 11,%1\n\t" \
2433 "mr %0,3\n\t" \
2434 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2435 VG_CONTRACT_FRAME_BY(512) \
2436 : /*out*/ "=r" (_res) \
2437 : /*in*/ "r" (&_argvec[2]) \
2438 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2439 ); \
2440 lval = (__typeof__(lval)) _res; \
2441 } while (0)
2442
2443#define CALL_FN_W_W(lval, orig, arg1) \
2444 do { \
2445 volatile OrigFn _orig = (orig); \
2446 volatile unsigned long _argvec[3+1]; \
2447 volatile unsigned long _res; \
2448 /* _argvec[0] holds current r2 across the call */ \
2449 _argvec[1] = (unsigned long)_orig.r2; \
2450 _argvec[2] = (unsigned long)_orig.nraddr; \
2451 _argvec[2+1] = (unsigned long)arg1; \
2452 __asm__ volatile( \
2453 "mr 11,%1\n\t" \
2454 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2455 "stw 2,-8(11)\n\t" /* save tocptr */ \
2456 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2457 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2458 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2459 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2460 "mr 11,%1\n\t" \
2461 "mr %0,3\n\t" \
2462 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2463 VG_CONTRACT_FRAME_BY(512) \
2464 : /*out*/ "=r" (_res) \
2465 : /*in*/ "r" (&_argvec[2]) \
2466 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2467 ); \
2468 lval = (__typeof__(lval)) _res; \
2469 } while (0)
2470
2471#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2472 do { \
2473 volatile OrigFn _orig = (orig); \
2474 volatile unsigned long _argvec[3+2]; \
2475 volatile unsigned long _res; \
2476 /* _argvec[0] holds current r2 across the call */ \
2477 _argvec[1] = (unsigned long)_orig.r2; \
2478 _argvec[2] = (unsigned long)_orig.nraddr; \
2479 _argvec[2+1] = (unsigned long)arg1; \
2480 _argvec[2+2] = (unsigned long)arg2; \
2481 __asm__ volatile( \
2482 "mr 11,%1\n\t" \
2483 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2484 "stw 2,-8(11)\n\t" /* save tocptr */ \
2485 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2486 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2487 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2488 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2489 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2490 "mr 11,%1\n\t" \
2491 "mr %0,3\n\t" \
2492 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2493 VG_CONTRACT_FRAME_BY(512) \
2494 : /*out*/ "=r" (_res) \
2495 : /*in*/ "r" (&_argvec[2]) \
2496 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2497 ); \
2498 lval = (__typeof__(lval)) _res; \
2499 } while (0)
2500
2501#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2502 do { \
2503 volatile OrigFn _orig = (orig); \
2504 volatile unsigned long _argvec[3+3]; \
2505 volatile unsigned long _res; \
2506 /* _argvec[0] holds current r2 across the call */ \
2507 _argvec[1] = (unsigned long)_orig.r2; \
2508 _argvec[2] = (unsigned long)_orig.nraddr; \
2509 _argvec[2+1] = (unsigned long)arg1; \
2510 _argvec[2+2] = (unsigned long)arg2; \
2511 _argvec[2+3] = (unsigned long)arg3; \
2512 __asm__ volatile( \
2513 "mr 11,%1\n\t" \
2514 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2515 "stw 2,-8(11)\n\t" /* save tocptr */ \
2516 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2517 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2518 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2519 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2520 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2521 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2522 "mr 11,%1\n\t" \
2523 "mr %0,3\n\t" \
2524 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2525 VG_CONTRACT_FRAME_BY(512) \
2526 : /*out*/ "=r" (_res) \
2527 : /*in*/ "r" (&_argvec[2]) \
2528 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2529 ); \
2530 lval = (__typeof__(lval)) _res; \
2531 } while (0)
2532
2533#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2534 do { \
2535 volatile OrigFn _orig = (orig); \
2536 volatile unsigned long _argvec[3+4]; \
2537 volatile unsigned long _res; \
2538 /* _argvec[0] holds current r2 across the call */ \
2539 _argvec[1] = (unsigned long)_orig.r2; \
2540 _argvec[2] = (unsigned long)_orig.nraddr; \
2541 _argvec[2+1] = (unsigned long)arg1; \
2542 _argvec[2+2] = (unsigned long)arg2; \
2543 _argvec[2+3] = (unsigned long)arg3; \
2544 _argvec[2+4] = (unsigned long)arg4; \
2545 __asm__ volatile( \
2546 "mr 11,%1\n\t" \
2547 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2548 "stw 2,-8(11)\n\t" /* save tocptr */ \
2549 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2550 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2551 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2552 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2553 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2554 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2555 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2556 "mr 11,%1\n\t" \
2557 "mr %0,3\n\t" \
2558 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2559 VG_CONTRACT_FRAME_BY(512) \
2560 : /*out*/ "=r" (_res) \
2561 : /*in*/ "r" (&_argvec[2]) \
2562 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2563 ); \
2564 lval = (__typeof__(lval)) _res; \
2565 } while (0)
2566
2567#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2568 do { \
2569 volatile OrigFn _orig = (orig); \
2570 volatile unsigned long _argvec[3+5]; \
2571 volatile unsigned long _res; \
2572 /* _argvec[0] holds current r2 across the call */ \
2573 _argvec[1] = (unsigned long)_orig.r2; \
2574 _argvec[2] = (unsigned long)_orig.nraddr; \
2575 _argvec[2+1] = (unsigned long)arg1; \
2576 _argvec[2+2] = (unsigned long)arg2; \
2577 _argvec[2+3] = (unsigned long)arg3; \
2578 _argvec[2+4] = (unsigned long)arg4; \
2579 _argvec[2+5] = (unsigned long)arg5; \
2580 __asm__ volatile( \
2581 "mr 11,%1\n\t" \
2582 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2583 "stw 2,-8(11)\n\t" /* save tocptr */ \
2584 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2585 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2586 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2587 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2588 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2589 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2590 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2591 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2592 "mr 11,%1\n\t" \
2593 "mr %0,3\n\t" \
2594 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2595 VG_CONTRACT_FRAME_BY(512) \
2596 : /*out*/ "=r" (_res) \
2597 : /*in*/ "r" (&_argvec[2]) \
2598 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2599 ); \
2600 lval = (__typeof__(lval)) _res; \
2601 } while (0)
2602
2603#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2604 do { \
2605 volatile OrigFn _orig = (orig); \
2606 volatile unsigned long _argvec[3+6]; \
2607 volatile unsigned long _res; \
2608 /* _argvec[0] holds current r2 across the call */ \
2609 _argvec[1] = (unsigned long)_orig.r2; \
2610 _argvec[2] = (unsigned long)_orig.nraddr; \
2611 _argvec[2+1] = (unsigned long)arg1; \
2612 _argvec[2+2] = (unsigned long)arg2; \
2613 _argvec[2+3] = (unsigned long)arg3; \
2614 _argvec[2+4] = (unsigned long)arg4; \
2615 _argvec[2+5] = (unsigned long)arg5; \
2616 _argvec[2+6] = (unsigned long)arg6; \
2617 __asm__ volatile( \
2618 "mr 11,%1\n\t" \
2619 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2620 "stw 2,-8(11)\n\t" /* save tocptr */ \
2621 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2622 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2623 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2624 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2625 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2626 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2627 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2628 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2629 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2630 "mr 11,%1\n\t" \
2631 "mr %0,3\n\t" \
2632 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2633 VG_CONTRACT_FRAME_BY(512) \
2634 : /*out*/ "=r" (_res) \
2635 : /*in*/ "r" (&_argvec[2]) \
2636 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2637 ); \
2638 lval = (__typeof__(lval)) _res; \
2639 } while (0)
2640
2641#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2642 arg7) \
2643 do { \
2644 volatile OrigFn _orig = (orig); \
2645 volatile unsigned long _argvec[3+7]; \
2646 volatile unsigned long _res; \
2647 /* _argvec[0] holds current r2 across the call */ \
2648 _argvec[1] = (unsigned long)_orig.r2; \
2649 _argvec[2] = (unsigned long)_orig.nraddr; \
2650 _argvec[2+1] = (unsigned long)arg1; \
2651 _argvec[2+2] = (unsigned long)arg2; \
2652 _argvec[2+3] = (unsigned long)arg3; \
2653 _argvec[2+4] = (unsigned long)arg4; \
2654 _argvec[2+5] = (unsigned long)arg5; \
2655 _argvec[2+6] = (unsigned long)arg6; \
2656 _argvec[2+7] = (unsigned long)arg7; \
2657 __asm__ volatile( \
2658 "mr 11,%1\n\t" \
2659 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2660 "stw 2,-8(11)\n\t" /* save tocptr */ \
2661 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2662 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2663 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2664 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2665 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2666 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2667 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2668 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2669 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2670 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2671 "mr 11,%1\n\t" \
2672 "mr %0,3\n\t" \
2673 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2674 VG_CONTRACT_FRAME_BY(512) \
2675 : /*out*/ "=r" (_res) \
2676 : /*in*/ "r" (&_argvec[2]) \
2677 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2678 ); \
2679 lval = (__typeof__(lval)) _res; \
2680 } while (0)
2681
2682#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2683 arg7,arg8) \
2684 do { \
2685 volatile OrigFn _orig = (orig); \
2686 volatile unsigned long _argvec[3+8]; \
2687 volatile unsigned long _res; \
2688 /* _argvec[0] holds current r2 across the call */ \
2689 _argvec[1] = (unsigned long)_orig.r2; \
2690 _argvec[2] = (unsigned long)_orig.nraddr; \
2691 _argvec[2+1] = (unsigned long)arg1; \
2692 _argvec[2+2] = (unsigned long)arg2; \
2693 _argvec[2+3] = (unsigned long)arg3; \
2694 _argvec[2+4] = (unsigned long)arg4; \
2695 _argvec[2+5] = (unsigned long)arg5; \
2696 _argvec[2+6] = (unsigned long)arg6; \
2697 _argvec[2+7] = (unsigned long)arg7; \
2698 _argvec[2+8] = (unsigned long)arg8; \
2699 __asm__ volatile( \
2700 "mr 11,%1\n\t" \
2701 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2702 "stw 2,-8(11)\n\t" /* save tocptr */ \
2703 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2704 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2705 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2706 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2707 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2708 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2709 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2710 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2711 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2712 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2713 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2714 "mr 11,%1\n\t" \
2715 "mr %0,3\n\t" \
2716 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2717 VG_CONTRACT_FRAME_BY(512) \
2718 : /*out*/ "=r" (_res) \
2719 : /*in*/ "r" (&_argvec[2]) \
2720 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2721 ); \
2722 lval = (__typeof__(lval)) _res; \
2723 } while (0)
2724
2725#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2726 arg7,arg8,arg9) \
2727 do { \
2728 volatile OrigFn _orig = (orig); \
2729 volatile unsigned long _argvec[3+9]; \
2730 volatile unsigned long _res; \
2731 /* _argvec[0] holds current r2 across the call */ \
2732 _argvec[1] = (unsigned long)_orig.r2; \
2733 _argvec[2] = (unsigned long)_orig.nraddr; \
2734 _argvec[2+1] = (unsigned long)arg1; \
2735 _argvec[2+2] = (unsigned long)arg2; \
2736 _argvec[2+3] = (unsigned long)arg3; \
2737 _argvec[2+4] = (unsigned long)arg4; \
2738 _argvec[2+5] = (unsigned long)arg5; \
2739 _argvec[2+6] = (unsigned long)arg6; \
2740 _argvec[2+7] = (unsigned long)arg7; \
2741 _argvec[2+8] = (unsigned long)arg8; \
2742 _argvec[2+9] = (unsigned long)arg9; \
2743 __asm__ volatile( \
2744 "mr 11,%1\n\t" \
2745 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2746 "stw 2,-8(11)\n\t" /* save tocptr */ \
2747 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2748 VG_EXPAND_FRAME_BY_trashes_r3(64) \
2749 /* arg9 */ \
2750 "lwz 3,36(11)\n\t" \
2751 "stw 3,56(1)\n\t" \
2752 /* args1-8 */ \
2753 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2754 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2755 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2756 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2757 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2758 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2759 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2760 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2761 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2762 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2763 "mr 11,%1\n\t" \
2764 "mr %0,3\n\t" \
2765 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2766 VG_CONTRACT_FRAME_BY(64) \
2767 VG_CONTRACT_FRAME_BY(512) \
2768 : /*out*/ "=r" (_res) \
2769 : /*in*/ "r" (&_argvec[2]) \
2770 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2771 ); \
2772 lval = (__typeof__(lval)) _res; \
2773 } while (0)
2774
2775#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2776 arg7,arg8,arg9,arg10) \
2777 do { \
2778 volatile OrigFn _orig = (orig); \
2779 volatile unsigned long _argvec[3+10]; \
2780 volatile unsigned long _res; \
2781 /* _argvec[0] holds current r2 across the call */ \
2782 _argvec[1] = (unsigned long)_orig.r2; \
2783 _argvec[2] = (unsigned long)_orig.nraddr; \
2784 _argvec[2+1] = (unsigned long)arg1; \
2785 _argvec[2+2] = (unsigned long)arg2; \
2786 _argvec[2+3] = (unsigned long)arg3; \
2787 _argvec[2+4] = (unsigned long)arg4; \
2788 _argvec[2+5] = (unsigned long)arg5; \
2789 _argvec[2+6] = (unsigned long)arg6; \
2790 _argvec[2+7] = (unsigned long)arg7; \
2791 _argvec[2+8] = (unsigned long)arg8; \
2792 _argvec[2+9] = (unsigned long)arg9; \
2793 _argvec[2+10] = (unsigned long)arg10; \
2794 __asm__ volatile( \
2795 "mr 11,%1\n\t" \
2796 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2797 "stw 2,-8(11)\n\t" /* save tocptr */ \
2798 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2799 VG_EXPAND_FRAME_BY_trashes_r3(64) \
2800 /* arg10 */ \
2801 "lwz 3,40(11)\n\t" \
2802 "stw 3,60(1)\n\t" \
2803 /* arg9 */ \
2804 "lwz 3,36(11)\n\t" \
2805 "stw 3,56(1)\n\t" \
2806 /* args1-8 */ \
2807 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2808 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2809 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2810 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2811 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2812 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2813 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2814 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2815 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2816 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2817 "mr 11,%1\n\t" \
2818 "mr %0,3\n\t" \
2819 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2820 VG_CONTRACT_FRAME_BY(64) \
2821 VG_CONTRACT_FRAME_BY(512) \
2822 : /*out*/ "=r" (_res) \
2823 : /*in*/ "r" (&_argvec[2]) \
2824 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2825 ); \
2826 lval = (__typeof__(lval)) _res; \
2827 } while (0)
2828
2829#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2830 arg7,arg8,arg9,arg10,arg11) \
2831 do { \
2832 volatile OrigFn _orig = (orig); \
2833 volatile unsigned long _argvec[3+11]; \
2834 volatile unsigned long _res; \
2835 /* _argvec[0] holds current r2 across the call */ \
2836 _argvec[1] = (unsigned long)_orig.r2; \
2837 _argvec[2] = (unsigned long)_orig.nraddr; \
2838 _argvec[2+1] = (unsigned long)arg1; \
2839 _argvec[2+2] = (unsigned long)arg2; \
2840 _argvec[2+3] = (unsigned long)arg3; \
2841 _argvec[2+4] = (unsigned long)arg4; \
2842 _argvec[2+5] = (unsigned long)arg5; \
2843 _argvec[2+6] = (unsigned long)arg6; \
2844 _argvec[2+7] = (unsigned long)arg7; \
2845 _argvec[2+8] = (unsigned long)arg8; \
2846 _argvec[2+9] = (unsigned long)arg9; \
2847 _argvec[2+10] = (unsigned long)arg10; \
2848 _argvec[2+11] = (unsigned long)arg11; \
2849 __asm__ volatile( \
2850 "mr 11,%1\n\t" \
2851 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2852 "stw 2,-8(11)\n\t" /* save tocptr */ \
2853 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2854 VG_EXPAND_FRAME_BY_trashes_r3(72) \
2855 /* arg11 */ \
2856 "lwz 3,44(11)\n\t" \
2857 "stw 3,64(1)\n\t" \
2858 /* arg10 */ \
2859 "lwz 3,40(11)\n\t" \
2860 "stw 3,60(1)\n\t" \
2861 /* arg9 */ \
2862 "lwz 3,36(11)\n\t" \
2863 "stw 3,56(1)\n\t" \
2864 /* args1-8 */ \
2865 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2866 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2867 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2868 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2869 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2870 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2871 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2872 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2873 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2874 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2875 "mr 11,%1\n\t" \
2876 "mr %0,3\n\t" \
2877 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2878 VG_CONTRACT_FRAME_BY(72) \
2879 VG_CONTRACT_FRAME_BY(512) \
2880 : /*out*/ "=r" (_res) \
2881 : /*in*/ "r" (&_argvec[2]) \
2882 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2883 ); \
2884 lval = (__typeof__(lval)) _res; \
2885 } while (0)
2886
2887#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2888 arg7,arg8,arg9,arg10,arg11,arg12) \
2889 do { \
2890 volatile OrigFn _orig = (orig); \
2891 volatile unsigned long _argvec[3+12]; \
2892 volatile unsigned long _res; \
2893 /* _argvec[0] holds current r2 across the call */ \
2894 _argvec[1] = (unsigned long)_orig.r2; \
2895 _argvec[2] = (unsigned long)_orig.nraddr; \
2896 _argvec[2+1] = (unsigned long)arg1; \
2897 _argvec[2+2] = (unsigned long)arg2; \
2898 _argvec[2+3] = (unsigned long)arg3; \
2899 _argvec[2+4] = (unsigned long)arg4; \
2900 _argvec[2+5] = (unsigned long)arg5; \
2901 _argvec[2+6] = (unsigned long)arg6; \
2902 _argvec[2+7] = (unsigned long)arg7; \
2903 _argvec[2+8] = (unsigned long)arg8; \
2904 _argvec[2+9] = (unsigned long)arg9; \
2905 _argvec[2+10] = (unsigned long)arg10; \
2906 _argvec[2+11] = (unsigned long)arg11; \
2907 _argvec[2+12] = (unsigned long)arg12; \
2908 __asm__ volatile( \
2909 "mr 11,%1\n\t" \
2910 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2911 "stw 2,-8(11)\n\t" /* save tocptr */ \
2912 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2913 VG_EXPAND_FRAME_BY_trashes_r3(72) \
2914 /* arg12 */ \
2915 "lwz 3,48(11)\n\t" \
2916 "stw 3,68(1)\n\t" \
2917 /* arg11 */ \
2918 "lwz 3,44(11)\n\t" \
2919 "stw 3,64(1)\n\t" \
2920 /* arg10 */ \
2921 "lwz 3,40(11)\n\t" \
2922 "stw 3,60(1)\n\t" \
2923 /* arg9 */ \
2924 "lwz 3,36(11)\n\t" \
2925 "stw 3,56(1)\n\t" \
2926 /* args1-8 */ \
2927 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2928 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2929 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2930 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2931 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2932 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2933 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2934 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2935 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2936 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2937 "mr 11,%1\n\t" \
2938 "mr %0,3\n\t" \
2939 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2940 VG_CONTRACT_FRAME_BY(72) \
2941 VG_CONTRACT_FRAME_BY(512) \
2942 : /*out*/ "=r" (_res) \
2943 : /*in*/ "r" (&_argvec[2]) \
2944 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2945 ); \
2946 lval = (__typeof__(lval)) _res; \
2947 } while (0)
2948
2949#endif /* PLAT_ppc32_aix5 */
2950
2951/* ------------------------ ppc64-aix5 ------------------------- */
2952
2953#if defined(PLAT_ppc64_aix5)
2954
2955/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2956
2957/* These regs are trashed by the hidden call. */
2958#define __CALLER_SAVED_REGS \
2959 "lr", "ctr", "xer", \
2960 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2961 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2962 "r11", "r12", "r13"
2963
2964/* Expand the stack frame, copying enough info that unwinding
2965 still works. Trashes r3. */
2966
2967#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
2968 "addi 1,1,-" #_n_fr "\n\t" \
2969 "ld 3," #_n_fr "(1)\n\t" \
2970 "std 3,0(1)\n\t"
2971
2972#define VG_CONTRACT_FRAME_BY(_n_fr) \
2973 "addi 1,1," #_n_fr "\n\t"
2974
2975/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
2976 long) == 8. */
2977
2978#define CALL_FN_W_v(lval, orig) \
2979 do { \
2980 volatile OrigFn _orig = (orig); \
2981 volatile unsigned long _argvec[3+0]; \
2982 volatile unsigned long _res; \
2983 /* _argvec[0] holds current r2 across the call */ \
2984 _argvec[1] = (unsigned long)_orig.r2; \
2985 _argvec[2] = (unsigned long)_orig.nraddr; \
2986 __asm__ volatile( \
2987 "mr 11,%1\n\t" \
2988 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2989 "std 2,-16(11)\n\t" /* save tocptr */ \
2990 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2991 "ld 11, 0(11)\n\t" /* target->r11 */ \
2992 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2993 "mr 11,%1\n\t" \
2994 "mr %0,3\n\t" \
2995 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2996 VG_CONTRACT_FRAME_BY(512) \
2997 : /*out*/ "=r" (_res) \
2998 : /*in*/ "r" (&_argvec[2]) \
2999 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3000 ); \
3001 lval = (__typeof__(lval)) _res; \
3002 } while (0)
3003
3004#define CALL_FN_W_W(lval, orig, arg1) \
3005 do { \
3006 volatile OrigFn _orig = (orig); \
3007 volatile unsigned long _argvec[3+1]; \
3008 volatile unsigned long _res; \
3009 /* _argvec[0] holds current r2 across the call */ \
3010 _argvec[1] = (unsigned long)_orig.r2; \
3011 _argvec[2] = (unsigned long)_orig.nraddr; \
3012 _argvec[2+1] = (unsigned long)arg1; \
3013 __asm__ volatile( \
3014 "mr 11,%1\n\t" \
3015 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3016 "std 2,-16(11)\n\t" /* save tocptr */ \
3017 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3018 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3019 "ld 11, 0(11)\n\t" /* target->r11 */ \
3020 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3021 "mr 11,%1\n\t" \
3022 "mr %0,3\n\t" \
3023 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3024 VG_CONTRACT_FRAME_BY(512) \
3025 : /*out*/ "=r" (_res) \
3026 : /*in*/ "r" (&_argvec[2]) \
3027 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3028 ); \
3029 lval = (__typeof__(lval)) _res; \
3030 } while (0)
3031
3032#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3033 do { \
3034 volatile OrigFn _orig = (orig); \
3035 volatile unsigned long _argvec[3+2]; \
3036 volatile unsigned long _res; \
3037 /* _argvec[0] holds current r2 across the call */ \
3038 _argvec[1] = (unsigned long)_orig.r2; \
3039 _argvec[2] = (unsigned long)_orig.nraddr; \
3040 _argvec[2+1] = (unsigned long)arg1; \
3041 _argvec[2+2] = (unsigned long)arg2; \
3042 __asm__ volatile( \
3043 "mr 11,%1\n\t" \
3044 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3045 "std 2,-16(11)\n\t" /* save tocptr */ \
3046 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3047 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3048 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3049 "ld 11, 0(11)\n\t" /* target->r11 */ \
3050 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3051 "mr 11,%1\n\t" \
3052 "mr %0,3\n\t" \
3053 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3054 VG_CONTRACT_FRAME_BY(512) \
3055 : /*out*/ "=r" (_res) \
3056 : /*in*/ "r" (&_argvec[2]) \
3057 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3058 ); \
3059 lval = (__typeof__(lval)) _res; \
3060 } while (0)
3061
3062#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3063 do { \
3064 volatile OrigFn _orig = (orig); \
3065 volatile unsigned long _argvec[3+3]; \
3066 volatile unsigned long _res; \
3067 /* _argvec[0] holds current r2 across the call */ \
3068 _argvec[1] = (unsigned long)_orig.r2; \
3069 _argvec[2] = (unsigned long)_orig.nraddr; \
3070 _argvec[2+1] = (unsigned long)arg1; \
3071 _argvec[2+2] = (unsigned long)arg2; \
3072 _argvec[2+3] = (unsigned long)arg3; \
3073 __asm__ volatile( \
3074 "mr 11,%1\n\t" \
3075 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3076 "std 2,-16(11)\n\t" /* save tocptr */ \
3077 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3078 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3079 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3080 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3081 "ld 11, 0(11)\n\t" /* target->r11 */ \
3082 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3083 "mr 11,%1\n\t" \
3084 "mr %0,3\n\t" \
3085 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3086 VG_CONTRACT_FRAME_BY(512) \
3087 : /*out*/ "=r" (_res) \
3088 : /*in*/ "r" (&_argvec[2]) \
3089 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3090 ); \
3091 lval = (__typeof__(lval)) _res; \
3092 } while (0)
3093
3094#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3095 do { \
3096 volatile OrigFn _orig = (orig); \
3097 volatile unsigned long _argvec[3+4]; \
3098 volatile unsigned long _res; \
3099 /* _argvec[0] holds current r2 across the call */ \
3100 _argvec[1] = (unsigned long)_orig.r2; \
3101 _argvec[2] = (unsigned long)_orig.nraddr; \
3102 _argvec[2+1] = (unsigned long)arg1; \
3103 _argvec[2+2] = (unsigned long)arg2; \
3104 _argvec[2+3] = (unsigned long)arg3; \
3105 _argvec[2+4] = (unsigned long)arg4; \
3106 __asm__ volatile( \
3107 "mr 11,%1\n\t" \
3108 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3109 "std 2,-16(11)\n\t" /* save tocptr */ \
3110 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3111 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3112 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3113 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3114 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3115 "ld 11, 0(11)\n\t" /* target->r11 */ \
3116 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3117 "mr 11,%1\n\t" \
3118 "mr %0,3\n\t" \
3119 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3120 VG_CONTRACT_FRAME_BY(512) \
3121 : /*out*/ "=r" (_res) \
3122 : /*in*/ "r" (&_argvec[2]) \
3123 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3124 ); \
3125 lval = (__typeof__(lval)) _res; \
3126 } while (0)
3127
3128#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3129 do { \
3130 volatile OrigFn _orig = (orig); \
3131 volatile unsigned long _argvec[3+5]; \
3132 volatile unsigned long _res; \
3133 /* _argvec[0] holds current r2 across the call */ \
3134 _argvec[1] = (unsigned long)_orig.r2; \
3135 _argvec[2] = (unsigned long)_orig.nraddr; \
3136 _argvec[2+1] = (unsigned long)arg1; \
3137 _argvec[2+2] = (unsigned long)arg2; \
3138 _argvec[2+3] = (unsigned long)arg3; \
3139 _argvec[2+4] = (unsigned long)arg4; \
3140 _argvec[2+5] = (unsigned long)arg5; \
3141 __asm__ volatile( \
3142 "mr 11,%1\n\t" \
3143 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3144 "std 2,-16(11)\n\t" /* save tocptr */ \
3145 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3146 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3147 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3148 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3149 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3150 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3151 "ld 11, 0(11)\n\t" /* target->r11 */ \
3152 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3153 "mr 11,%1\n\t" \
3154 "mr %0,3\n\t" \
3155 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3156 VG_CONTRACT_FRAME_BY(512) \
3157 : /*out*/ "=r" (_res) \
3158 : /*in*/ "r" (&_argvec[2]) \
3159 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3160 ); \
3161 lval = (__typeof__(lval)) _res; \
3162 } while (0)
3163
3164#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3165 do { \
3166 volatile OrigFn _orig = (orig); \
3167 volatile unsigned long _argvec[3+6]; \
3168 volatile unsigned long _res; \
3169 /* _argvec[0] holds current r2 across the call */ \
3170 _argvec[1] = (unsigned long)_orig.r2; \
3171 _argvec[2] = (unsigned long)_orig.nraddr; \
3172 _argvec[2+1] = (unsigned long)arg1; \
3173 _argvec[2+2] = (unsigned long)arg2; \
3174 _argvec[2+3] = (unsigned long)arg3; \
3175 _argvec[2+4] = (unsigned long)arg4; \
3176 _argvec[2+5] = (unsigned long)arg5; \
3177 _argvec[2+6] = (unsigned long)arg6; \
3178 __asm__ volatile( \
3179 "mr 11,%1\n\t" \
3180 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3181 "std 2,-16(11)\n\t" /* save tocptr */ \
3182 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3183 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3184 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3185 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3186 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3187 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3188 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3189 "ld 11, 0(11)\n\t" /* target->r11 */ \
3190 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3191 "mr 11,%1\n\t" \
3192 "mr %0,3\n\t" \
3193 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3194 VG_CONTRACT_FRAME_BY(512) \
3195 : /*out*/ "=r" (_res) \
3196 : /*in*/ "r" (&_argvec[2]) \
3197 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3198 ); \
3199 lval = (__typeof__(lval)) _res; \
3200 } while (0)
3201
3202#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3203 arg7) \
3204 do { \
3205 volatile OrigFn _orig = (orig); \
3206 volatile unsigned long _argvec[3+7]; \
3207 volatile unsigned long _res; \
3208 /* _argvec[0] holds current r2 across the call */ \
3209 _argvec[1] = (unsigned long)_orig.r2; \
3210 _argvec[2] = (unsigned long)_orig.nraddr; \
3211 _argvec[2+1] = (unsigned long)arg1; \
3212 _argvec[2+2] = (unsigned long)arg2; \
3213 _argvec[2+3] = (unsigned long)arg3; \
3214 _argvec[2+4] = (unsigned long)arg4; \
3215 _argvec[2+5] = (unsigned long)arg5; \
3216 _argvec[2+6] = (unsigned long)arg6; \
3217 _argvec[2+7] = (unsigned long)arg7; \
3218 __asm__ volatile( \
3219 "mr 11,%1\n\t" \
3220 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3221 "std 2,-16(11)\n\t" /* save tocptr */ \
3222 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3223 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3224 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3225 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3226 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3227 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3228 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3229 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3230 "ld 11, 0(11)\n\t" /* target->r11 */ \
3231 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3232 "mr 11,%1\n\t" \
3233 "mr %0,3\n\t" \
3234 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3235 VG_CONTRACT_FRAME_BY(512) \
3236 : /*out*/ "=r" (_res) \
3237 : /*in*/ "r" (&_argvec[2]) \
3238 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3239 ); \
3240 lval = (__typeof__(lval)) _res; \
3241 } while (0)
3242
3243#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3244 arg7,arg8) \
3245 do { \
3246 volatile OrigFn _orig = (orig); \
3247 volatile unsigned long _argvec[3+8]; \
3248 volatile unsigned long _res; \
3249 /* _argvec[0] holds current r2 across the call */ \
3250 _argvec[1] = (unsigned long)_orig.r2; \
3251 _argvec[2] = (unsigned long)_orig.nraddr; \
3252 _argvec[2+1] = (unsigned long)arg1; \
3253 _argvec[2+2] = (unsigned long)arg2; \
3254 _argvec[2+3] = (unsigned long)arg3; \
3255 _argvec[2+4] = (unsigned long)arg4; \
3256 _argvec[2+5] = (unsigned long)arg5; \
3257 _argvec[2+6] = (unsigned long)arg6; \
3258 _argvec[2+7] = (unsigned long)arg7; \
3259 _argvec[2+8] = (unsigned long)arg8; \
3260 __asm__ volatile( \
3261 "mr 11,%1\n\t" \
3262 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3263 "std 2,-16(11)\n\t" /* save tocptr */ \
3264 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3265 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3266 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3267 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3268 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3269 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3270 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3271 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3272 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3273 "ld 11, 0(11)\n\t" /* target->r11 */ \
3274 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3275 "mr 11,%1\n\t" \
3276 "mr %0,3\n\t" \
3277 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3278 VG_CONTRACT_FRAME_BY(512) \
3279 : /*out*/ "=r" (_res) \
3280 : /*in*/ "r" (&_argvec[2]) \
3281 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3282 ); \
3283 lval = (__typeof__(lval)) _res; \
3284 } while (0)
3285
3286#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3287 arg7,arg8,arg9) \
3288 do { \
3289 volatile OrigFn _orig = (orig); \
3290 volatile unsigned long _argvec[3+9]; \
3291 volatile unsigned long _res; \
3292 /* _argvec[0] holds current r2 across the call */ \
3293 _argvec[1] = (unsigned long)_orig.r2; \
3294 _argvec[2] = (unsigned long)_orig.nraddr; \
3295 _argvec[2+1] = (unsigned long)arg1; \
3296 _argvec[2+2] = (unsigned long)arg2; \
3297 _argvec[2+3] = (unsigned long)arg3; \
3298 _argvec[2+4] = (unsigned long)arg4; \
3299 _argvec[2+5] = (unsigned long)arg5; \
3300 _argvec[2+6] = (unsigned long)arg6; \
3301 _argvec[2+7] = (unsigned long)arg7; \
3302 _argvec[2+8] = (unsigned long)arg8; \
3303 _argvec[2+9] = (unsigned long)arg9; \
3304 __asm__ volatile( \
3305 "mr 11,%1\n\t" \
3306 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3307 "std 2,-16(11)\n\t" /* save tocptr */ \
3308 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3309 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3310 /* arg9 */ \
3311 "ld 3,72(11)\n\t" \
3312 "std 3,112(1)\n\t" \
3313 /* args1-8 */ \
3314 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3315 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3316 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3317 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3318 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3319 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3320 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3321 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3322 "ld 11, 0(11)\n\t" /* target->r11 */ \
3323 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3324 "mr 11,%1\n\t" \
3325 "mr %0,3\n\t" \
3326 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3327 VG_CONTRACT_FRAME_BY(128) \
3328 VG_CONTRACT_FRAME_BY(512) \
3329 : /*out*/ "=r" (_res) \
3330 : /*in*/ "r" (&_argvec[2]) \
3331 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3332 ); \
3333 lval = (__typeof__(lval)) _res; \
3334 } while (0)
3335
3336#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3337 arg7,arg8,arg9,arg10) \
3338 do { \
3339 volatile OrigFn _orig = (orig); \
3340 volatile unsigned long _argvec[3+10]; \
3341 volatile unsigned long _res; \
3342 /* _argvec[0] holds current r2 across the call */ \
3343 _argvec[1] = (unsigned long)_orig.r2; \
3344 _argvec[2] = (unsigned long)_orig.nraddr; \
3345 _argvec[2+1] = (unsigned long)arg1; \
3346 _argvec[2+2] = (unsigned long)arg2; \
3347 _argvec[2+3] = (unsigned long)arg3; \
3348 _argvec[2+4] = (unsigned long)arg4; \
3349 _argvec[2+5] = (unsigned long)arg5; \
3350 _argvec[2+6] = (unsigned long)arg6; \
3351 _argvec[2+7] = (unsigned long)arg7; \
3352 _argvec[2+8] = (unsigned long)arg8; \
3353 _argvec[2+9] = (unsigned long)arg9; \
3354 _argvec[2+10] = (unsigned long)arg10; \
3355 __asm__ volatile( \
3356 "mr 11,%1\n\t" \
3357 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3358 "std 2,-16(11)\n\t" /* save tocptr */ \
3359 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3360 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3361 /* arg10 */ \
3362 "ld 3,80(11)\n\t" \
3363 "std 3,120(1)\n\t" \
3364 /* arg9 */ \
3365 "ld 3,72(11)\n\t" \
3366 "std 3,112(1)\n\t" \
3367 /* args1-8 */ \
3368 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3369 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3370 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3371 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3372 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3373 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3374 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3375 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3376 "ld 11, 0(11)\n\t" /* target->r11 */ \
3377 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3378 "mr 11,%1\n\t" \
3379 "mr %0,3\n\t" \
3380 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3381 VG_CONTRACT_FRAME_BY(128) \
3382 VG_CONTRACT_FRAME_BY(512) \
3383 : /*out*/ "=r" (_res) \
3384 : /*in*/ "r" (&_argvec[2]) \
3385 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3386 ); \
3387 lval = (__typeof__(lval)) _res; \
3388 } while (0)
3389
3390#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3391 arg7,arg8,arg9,arg10,arg11) \
3392 do { \
3393 volatile OrigFn _orig = (orig); \
3394 volatile unsigned long _argvec[3+11]; \
3395 volatile unsigned long _res; \
3396 /* _argvec[0] holds current r2 across the call */ \
3397 _argvec[1] = (unsigned long)_orig.r2; \
3398 _argvec[2] = (unsigned long)_orig.nraddr; \
3399 _argvec[2+1] = (unsigned long)arg1; \
3400 _argvec[2+2] = (unsigned long)arg2; \
3401 _argvec[2+3] = (unsigned long)arg3; \
3402 _argvec[2+4] = (unsigned long)arg4; \
3403 _argvec[2+5] = (unsigned long)arg5; \
3404 _argvec[2+6] = (unsigned long)arg6; \
3405 _argvec[2+7] = (unsigned long)arg7; \
3406 _argvec[2+8] = (unsigned long)arg8; \
3407 _argvec[2+9] = (unsigned long)arg9; \
3408 _argvec[2+10] = (unsigned long)arg10; \
3409 _argvec[2+11] = (unsigned long)arg11; \
3410 __asm__ volatile( \
3411 "mr 11,%1\n\t" \
3412 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3413 "std 2,-16(11)\n\t" /* save tocptr */ \
3414 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3415 VG_EXPAND_FRAME_BY_trashes_r3(144) \
3416 /* arg11 */ \
3417 "ld 3,88(11)\n\t" \
3418 "std 3,128(1)\n\t" \
3419 /* arg10 */ \
3420 "ld 3,80(11)\n\t" \
3421 "std 3,120(1)\n\t" \
3422 /* arg9 */ \
3423 "ld 3,72(11)\n\t" \
3424 "std 3,112(1)\n\t" \
3425 /* args1-8 */ \
3426 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3427 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3428 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3429 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3430 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3431 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3432 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3433 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3434 "ld 11, 0(11)\n\t" /* target->r11 */ \
3435 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3436 "mr 11,%1\n\t" \
3437 "mr %0,3\n\t" \
3438 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3439 VG_CONTRACT_FRAME_BY(144) \
3440 VG_CONTRACT_FRAME_BY(512) \
3441 : /*out*/ "=r" (_res) \
3442 : /*in*/ "r" (&_argvec[2]) \
3443 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3444 ); \
3445 lval = (__typeof__(lval)) _res; \
3446 } while (0)
3447
3448#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3449 arg7,arg8,arg9,arg10,arg11,arg12) \
3450 do { \
3451 volatile OrigFn _orig = (orig); \
3452 volatile unsigned long _argvec[3+12]; \
3453 volatile unsigned long _res; \
3454 /* _argvec[0] holds current r2 across the call */ \
3455 _argvec[1] = (unsigned long)_orig.r2; \
3456 _argvec[2] = (unsigned long)_orig.nraddr; \
3457 _argvec[2+1] = (unsigned long)arg1; \
3458 _argvec[2+2] = (unsigned long)arg2; \
3459 _argvec[2+3] = (unsigned long)arg3; \
3460 _argvec[2+4] = (unsigned long)arg4; \
3461 _argvec[2+5] = (unsigned long)arg5; \
3462 _argvec[2+6] = (unsigned long)arg6; \
3463 _argvec[2+7] = (unsigned long)arg7; \
3464 _argvec[2+8] = (unsigned long)arg8; \
3465 _argvec[2+9] = (unsigned long)arg9; \
3466 _argvec[2+10] = (unsigned long)arg10; \
3467 _argvec[2+11] = (unsigned long)arg11; \
3468 _argvec[2+12] = (unsigned long)arg12; \
3469 __asm__ volatile( \
3470 "mr 11,%1\n\t" \
3471 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3472 "std 2,-16(11)\n\t" /* save tocptr */ \
3473 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3474 VG_EXPAND_FRAME_BY_trashes_r3(144) \
3475 /* arg12 */ \
3476 "ld 3,96(11)\n\t" \
3477 "std 3,136(1)\n\t" \
3478 /* arg11 */ \
3479 "ld 3,88(11)\n\t" \
3480 "std 3,128(1)\n\t" \
3481 /* arg10 */ \
3482 "ld 3,80(11)\n\t" \
3483 "std 3,120(1)\n\t" \
3484 /* arg9 */ \
3485 "ld 3,72(11)\n\t" \
3486 "std 3,112(1)\n\t" \
3487 /* args1-8 */ \
3488 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3489 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3490 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3491 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3492 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3493 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3494 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3495 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3496 "ld 11, 0(11)\n\t" /* target->r11 */ \
3497 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3498 "mr 11,%1\n\t" \
3499 "mr %0,3\n\t" \
3500 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3501 VG_CONTRACT_FRAME_BY(144) \
3502 VG_CONTRACT_FRAME_BY(512) \
3503 : /*out*/ "=r" (_res) \
3504 : /*in*/ "r" (&_argvec[2]) \
3505 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3506 ); \
3507 lval = (__typeof__(lval)) _res; \
3508 } while (0)
3509
3510#endif /* PLAT_ppc64_aix5 */
sewardj9734b202006-01-17 01:49:37 +00003511
sewardj0ec07f32006-01-12 12:32:32 +00003512
3513/* ------------------------------------------------------------------ */
3514/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
3515/* */
njn30d76c62005-06-18 15:07:39 +00003516/* ------------------------------------------------------------------ */
3517
sewardj2e93c502002-04-12 11:12:52 +00003518/* Some request codes. There are many more of these, but most are not
3519 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00003520 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00003521
sewardj0ec07f32006-01-12 12:32:32 +00003522 Core ones are in the range 0x00000000--0x0000ffff. The non-public
3523 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00003524*/
3525
sewardj0ec07f32006-01-12 12:32:32 +00003526/* These macros are used by tools -- they must be public, but don't
3527 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00003528#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00003529 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00003530#define VG_IS_TOOL_USERREQ(a, b, v) \
3531 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00003532
sewardj5ce4b152006-03-11 12:57:41 +00003533/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
3534 This enum comprises an ABI exported by Valgrind to programs
3535 which use client requests. DO NOT CHANGE THE ORDER OF THESE
3536 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00003537typedef
njn4c791212003-05-02 17:53:54 +00003538 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
3539 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00003540
sewardj0ec07f32006-01-12 12:32:32 +00003541 /* These allow any function to be called from the simulated
3542 CPU but run on the real CPU. Nb: the first arg passed to
3543 the function is always the ThreadId of the running
3544 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00003545 function, etc. */
njn4c791212003-05-02 17:53:54 +00003546 VG_USERREQ__CLIENT_CALL0 = 0x1101,
3547 VG_USERREQ__CLIENT_CALL1 = 0x1102,
3548 VG_USERREQ__CLIENT_CALL2 = 0x1103,
3549 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00003550
sewardj0ec07f32006-01-12 12:32:32 +00003551 /* Can be useful in regression testing suites -- eg. can
3552 send Valgrind's output to /dev/null and still count
3553 errors. */
njn4c791212003-05-02 17:53:54 +00003554 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00003555
sewardj0ec07f32006-01-12 12:32:32 +00003556 /* These are useful and can be interpreted by any tool that
3557 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00003558 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
3559 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00003560 /* Memory pool support. */
3561 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
3562 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
3563 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
3564 VG_USERREQ__MEMPOOL_FREE = 0x1306,
sewardj2c1c9df2006-07-28 00:06:37 +00003565 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
sewardjc740d762006-10-05 17:59:23 +00003566 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
3567 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
3568 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
njnd7994182003-10-02 13:44:04 +00003569
fitzhardinge39de4b42003-10-31 07:12:21 +00003570 /* Allow printfs to valgrind log. */
njn30d76c62005-06-18 15:07:39 +00003571 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00003572 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
3573
3574 /* Stack support. */
3575 VG_USERREQ__STACK_REGISTER = 0x1501,
3576 VG_USERREQ__STACK_DEREGISTER = 0x1502,
sewardj315dc8d2006-08-28 21:13:06 +00003577 VG_USERREQ__STACK_CHANGE = 0x1503
njn25e49d8e72002-09-23 09:36:25 +00003578 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00003579
sewardj0ec07f32006-01-12 12:32:32 +00003580#if !defined(__GNUC__)
3581# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00003582#endif
sewardj2e93c502002-04-12 11:12:52 +00003583
sewardj0ec07f32006-01-12 12:32:32 +00003584/* Returns the number of Valgrinds this code is running under. That
3585 is, 0 if running natively, 1 if running under Valgrind, 2 if
3586 running under Valgrind which is running under another Valgrind,
3587 etc. */
3588#define RUNNING_ON_VALGRIND __extension__ \
3589 ({unsigned int _qzz_res; \
3590 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \
3591 VG_USERREQ__RUNNING_ON_VALGRIND, \
sewardj9af10a12006-02-01 14:59:42 +00003592 0, 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00003593 _qzz_res; \
sewardjde4a1d02002-03-22 01:27:54 +00003594 })
3595
3596
sewardj18d75132002-05-16 11:06:21 +00003597/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
3598 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
3599 since it provides a way to make sure valgrind will retranslate the
3600 invalidated area. Returns no value. */
sewardj0ec07f32006-01-12 12:32:32 +00003601#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
3602 {unsigned int _qzz_res; \
3603 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3604 VG_USERREQ__DISCARD_TRANSLATIONS, \
sewardj9af10a12006-02-01 14:59:42 +00003605 _qzz_addr, _qzz_len, 0, 0, 0); \
sewardj18d75132002-05-16 11:06:21 +00003606 }
3607
njn26aba4d2005-05-16 13:31:23 +00003608
sewardj0ec07f32006-01-12 12:32:32 +00003609/* These requests are for getting Valgrind itself to print something.
3610 Possibly with a backtrace. This is a really ugly hack. */
3611
3612#if defined(NVALGRIND)
3613
3614# define VALGRIND_PRINTF(...)
3615# define VALGRIND_PRINTF_BACKTRACE(...)
njn26aba4d2005-05-16 13:31:23 +00003616
3617#else /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00003618
sewardj7eca0cc2006-04-12 17:15:35 +00003619/* Modern GCC will optimize the static routine out if unused,
3620 and unused attribute will shut down warnings about it. */
3621static int VALGRIND_PRINTF(const char *format, ...)
3622 __attribute__((format(__printf__, 1, 2), __unused__));
3623static int
fitzhardingea09a1b52003-11-07 23:09:48 +00003624VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00003625{
njnc6168192004-11-29 13:54:10 +00003626 unsigned long _qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00003627 va_list vargs;
3628 va_start(vargs, format);
sewardj0ec07f32006-01-12 12:32:32 +00003629 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF,
sewardj9af10a12006-02-01 14:59:42 +00003630 (unsigned long)format, (unsigned long)vargs,
3631 0, 0, 0);
fitzhardinge39de4b42003-10-31 07:12:21 +00003632 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00003633 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00003634}
3635
sewardj7eca0cc2006-04-12 17:15:35 +00003636static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
3637 __attribute__((format(__printf__, 1, 2), __unused__));
3638static int
fitzhardingea09a1b52003-11-07 23:09:48 +00003639VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00003640{
njnc6168192004-11-29 13:54:10 +00003641 unsigned long _qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00003642 va_list vargs;
3643 va_start(vargs, format);
sewardj0ec07f32006-01-12 12:32:32 +00003644 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE,
sewardj9af10a12006-02-01 14:59:42 +00003645 (unsigned long)format, (unsigned long)vargs,
3646 0, 0, 0);
fitzhardinge39de4b42003-10-31 07:12:21 +00003647 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00003648 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00003649}
3650
fitzhardinge39de4b42003-10-31 07:12:21 +00003651#endif /* NVALGRIND */
sewardj18d75132002-05-16 11:06:21 +00003652
sewardj0ec07f32006-01-12 12:32:32 +00003653
njn3e884182003-04-15 13:03:23 +00003654/* These requests allow control to move from the simulated CPU to the
njn1319b492006-11-20 22:02:40 +00003655 real CPU, calling an arbitary function.
3656
3657 Note that the current ThreadId is inserted as the first argument.
3658 So this call:
3659
3660 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
3661
3662 requires f to have this signature:
3663
3664 Word f(Word tid, Word arg1, Word arg2)
3665
3666 where "Word" is a word-sized type.
3667*/
sewardj0ec07f32006-01-12 12:32:32 +00003668#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
sewardj315dc8d2006-08-28 21:13:06 +00003669 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00003670 ({unsigned long _qyy_res; \
3671 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3672 VG_USERREQ__CLIENT_CALL0, \
3673 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00003674 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00003675 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00003676 })
3677
sewardj0ec07f32006-01-12 12:32:32 +00003678#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
sewardj315dc8d2006-08-28 21:13:06 +00003679 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00003680 ({unsigned long _qyy_res; \
3681 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3682 VG_USERREQ__CLIENT_CALL1, \
3683 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00003684 _qyy_arg1, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00003685 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00003686 })
3687
sewardj0ec07f32006-01-12 12:32:32 +00003688#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
sewardj315dc8d2006-08-28 21:13:06 +00003689 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00003690 ({unsigned long _qyy_res; \
3691 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3692 VG_USERREQ__CLIENT_CALL2, \
3693 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00003694 _qyy_arg1, _qyy_arg2, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00003695 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00003696 })
3697
sewardj0ec07f32006-01-12 12:32:32 +00003698#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
sewardj315dc8d2006-08-28 21:13:06 +00003699 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00003700 ({unsigned long _qyy_res; \
3701 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3702 VG_USERREQ__CLIENT_CALL3, \
3703 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00003704 _qyy_arg1, _qyy_arg2, \
3705 _qyy_arg3, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00003706 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00003707 })
3708
3709
nethercote7cc9c232004-01-21 15:08:04 +00003710/* Counts the number of errors that have been recorded by a tool. Nb:
3711 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00003712 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00003713#define VALGRIND_COUNT_ERRORS \
sewardj315dc8d2006-08-28 21:13:06 +00003714 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00003715 ({unsigned int _qyy_res; \
3716 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3717 VG_USERREQ__COUNT_ERRORS, \
sewardj9af10a12006-02-01 14:59:42 +00003718 0, 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00003719 _qyy_res; \
njn47363ab2003-04-21 13:24:40 +00003720 })
3721
njnd7994182003-10-02 13:44:04 +00003722/* Mark a block of memory as having been allocated by a malloc()-like
3723 function. `addr' is the start of the usable block (ie. after any
3724 redzone) `rzB' is redzone size if the allocator can apply redzones;
3725 use '0' if not. Adding redzones makes it more likely Valgrind will spot
3726 block overruns. `is_zeroed' indicates if the memory is zeroed, as it is
3727 for calloc(). Put it immediately after the point where a block is
3728 allocated.
3729
njn0fc5cbd2006-10-18 21:50:26 +00003730 If you're using Memcheck: If you're allocating memory via superblocks,
3731 and then handing out small chunks of each superblock, if you don't have
3732 redzones on your small blocks, it's worth marking the superblock with
3733 VALGRIND_MAKE_MEM_NOACCESS when it's created, so that block overruns are
3734 detected. But if you can put redzones on, it's probably better to not do
3735 this, so that messages for small overruns are described in terms of the
3736 small block rather than the superblock (but if you have a big overrun
3737 that skips over a redzone, you could miss an error this way). See
3738 memcheck/tests/custom_alloc.c for an example.
njnd7994182003-10-02 13:44:04 +00003739
njn479db772006-06-02 22:32:02 +00003740 WARNING: if your allocator uses malloc() or 'new' to allocate
3741 superblocks, rather than mmap() or brk(), this will not work properly --
3742 you'll likely get assertion failures during leak detection. This is
3743 because Valgrind doesn't like seeing overlapping heap blocks. Sorry.
3744
njnd7994182003-10-02 13:44:04 +00003745 Nb: block must be freed via a free()-like function specified
3746 with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */
sewardj0ec07f32006-01-12 12:32:32 +00003747#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
3748 {unsigned int _qzz_res; \
3749 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3750 VG_USERREQ__MALLOCLIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00003751 addr, sizeB, rzB, is_zeroed, 0); \
njnd7994182003-10-02 13:44:04 +00003752 }
3753
3754/* Mark a block of memory as having been freed by a free()-like function.
3755 `rzB' is redzone size; it must match that given to
3756 VALGRIND_MALLOCLIKE_BLOCK. Memory not freed will be detected by the leak
3757 checker. Put it immediately after the point where the block is freed. */
sewardj0ec07f32006-01-12 12:32:32 +00003758#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
3759 {unsigned int _qzz_res; \
3760 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3761 VG_USERREQ__FREELIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00003762 addr, rzB, 0, 0, 0); \
njnd7994182003-10-02 13:44:04 +00003763 }
3764
rjwalshbc0bb832004-06-19 18:12:36 +00003765/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003766#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
3767 {unsigned int _qzz_res; \
3768 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3769 VG_USERREQ__CREATE_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00003770 pool, rzB, is_zeroed, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00003771 }
3772
3773/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003774#define VALGRIND_DESTROY_MEMPOOL(pool) \
3775 {unsigned int _qzz_res; \
3776 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3777 VG_USERREQ__DESTROY_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00003778 pool, 0, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00003779 }
3780
3781/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003782#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
3783 {unsigned int _qzz_res; \
3784 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3785 VG_USERREQ__MEMPOOL_ALLOC, \
sewardj9af10a12006-02-01 14:59:42 +00003786 pool, addr, size, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00003787 }
3788
3789/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003790#define VALGRIND_MEMPOOL_FREE(pool, addr) \
3791 {unsigned int _qzz_res; \
3792 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3793 VG_USERREQ__MEMPOOL_FREE, \
sewardj9af10a12006-02-01 14:59:42 +00003794 pool, addr, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00003795 }
3796
sewardj2c1c9df2006-07-28 00:06:37 +00003797/* Disassociate any pieces outside a particular range. */
3798#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
3799 {unsigned int _qzz_res; \
3800 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3801 VG_USERREQ__MEMPOOL_TRIM, \
3802 pool, addr, size, 0, 0); \
3803 }
3804
sewardjc740d762006-10-05 17:59:23 +00003805/* Resize and/or move a piece associated with a memory pool. */
3806#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
3807 {unsigned int _qzz_res; \
3808 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3809 VG_USERREQ__MOVE_MEMPOOL, \
3810 poolA, poolB, 0, 0, 0); \
3811 }
3812
3813/* Resize and/or move a piece associated with a memory pool. */
3814#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
3815 {unsigned int _qzz_res; \
3816 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3817 VG_USERREQ__MEMPOOL_CHANGE, \
3818 pool, addrA, addrB, size, 0); \
3819 }
3820
3821/* Return 1 if a mempool exists, else 0. */
3822#define VALGRIND_MEMPOOL_EXISTS(pool) \
3823 ({unsigned int _qzz_res; \
3824 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3825 VG_USERREQ__MEMPOOL_EXISTS, \
3826 pool, 0, 0, 0, 0); \
3827 _qzz_res; \
3828 })
3829
rjwalsh0140af52005-06-04 20:42:33 +00003830/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00003831#define VALGRIND_STACK_REGISTER(start, end) \
3832 ({unsigned int _qzz_res; \
3833 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3834 VG_USERREQ__STACK_REGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00003835 start, end, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00003836 _qzz_res; \
rjwalsh0140af52005-06-04 20:42:33 +00003837 })
3838
3839/* Unmark the piece of memory associated with a stack id as being a
3840 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00003841#define VALGRIND_STACK_DEREGISTER(id) \
3842 {unsigned int _qzz_res; \
3843 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3844 VG_USERREQ__STACK_DEREGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00003845 id, 0, 0, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00003846 }
3847
3848/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00003849#define VALGRIND_STACK_CHANGE(id, start, end) \
3850 {unsigned int _qzz_res; \
3851 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3852 VG_USERREQ__STACK_CHANGE, \
sewardj9af10a12006-02-01 14:59:42 +00003853 id, start, end, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00003854 }
3855
sewardj0ec07f32006-01-12 12:32:32 +00003856
sewardjf5c1a7f2006-10-17 01:32:48 +00003857#undef PLAT_x86_linux
3858#undef PLAT_amd64_linux
3859#undef PLAT_ppc32_linux
3860#undef PLAT_ppc64_linux
3861#undef PLAT_ppc32_aix5
3862#undef PLAT_ppc64_aix5
sewardj0ec07f32006-01-12 12:32:32 +00003863
njn3e884182003-04-15 13:03:23 +00003864#endif /* __VALGRIND_H */