blob: b5c8222b4acaa624da84d05163b99e5e98e37720 [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
njn53612422005-03-12 16:22:54 +000015 Copyright (C) 2000-2005 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
sewardj0ec07f32006-01-12 12:32:32 +000082/* Derive some tags indicating what the target architecture is. Note
83 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
87 latter. */
88#undef ARCH_x86
89#undef ARCH_amd64
90#undef ARCH_ppc32
91#undef ARCH_ppc64
92
93#if defined(__i386__)
94# define ARCH_x86 1
95#elif defined(__x86_64__)
96# define ARCH_amd64 1
97#elif defined(__powerpc__) && !defined(__powerpc64__)
98# define ARCH_ppc32 1
99#elif defined(__powerpc__) && defined(__powerpc64__)
100# define ARCH_ppc64 1
sewardjb5f6f512005-03-10 23:59:00 +0000101#endif
102
sewardj0ec07f32006-01-12 12:32:32 +0000103/* If we're not compiling for our target architecture, don't generate
104 any inline asms. */
105#if !defined(ARCH_x86) && !defined(ARCH_amd64) \
106 && !defined(ARCH_ppc32) && !defined(ARCH_ppc64)
107# if !defined(NVALGRIND)
108# define NVALGRIND 1
109# endif
110#endif
111
112
njn30d76c62005-06-18 15:07:39 +0000113/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000114/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
115/* in here of use to end-users -- skip to the next section. */
njn30d76c62005-06-18 15:07:39 +0000116/* ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000117
sewardj0ec07f32006-01-12 12:32:32 +0000118#if defined(NVALGRIND)
njn26aba4d2005-05-16 13:31:23 +0000119
120/* Define NVALGRIND to completely remove the Valgrind magic sequence
sewardj0ec07f32006-01-12 12:32:32 +0000121 from the compiled code (analogous to NDEBUG's effects on
122 assert()) */
123#define VALGRIND_DO_CLIENT_REQUEST( \
124 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000125 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000126 { \
127 (_zzq_rlval) = (_zzq_default); \
njn26aba4d2005-05-16 13:31:23 +0000128 }
129
sewardj0ec07f32006-01-12 12:32:32 +0000130#else /* ! NVALGRIND */
nethercotee90c6832004-10-18 18:07:49 +0000131
sewardj0ec07f32006-01-12 12:32:32 +0000132/* The following defines the magic code sequences which the JITter
133 spots and handles magically. Don't look too closely at them as
134 they will rot your brain.
135
136 The assembly code sequences for all architectures is in this one
137 file. This is because this file must be stand-alone, and we don't
138 want to have multiple files.
139
140 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
141 value gets put in the return slot, so that everything works when
142 this is executed not under Valgrind. Args are passed in a memory
143 block, and so there's no intrinsic limit to the number that could
sewardj9af10a12006-02-01 14:59:42 +0000144 be passed, but it's currently five.
nethercotee90c6832004-10-18 18:07:49 +0000145
nethercote54265442004-10-26 12:56:58 +0000146 The macro args are:
147 _zzq_rlval result lvalue
148 _zzq_default default value (result returned when running on real CPU)
149 _zzq_request request code
sewardj9af10a12006-02-01 14:59:42 +0000150 _zzq_arg1..5 request params
nethercote54265442004-10-26 12:56:58 +0000151
sewardj0ec07f32006-01-12 12:32:32 +0000152 The other two macros are used to support function wrapping, and are
sewardjd68ac3e2006-01-20 14:31:57 +0000153 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
154 guest's NRADDR pseudo-register and whatever other information is
155 needed to safely run the call original from the wrapper: on
156 ppc64-linux, the R2 value at the divert point is also needed. This
157 information is abstracted into a user-visible type, OrigFn.
158
159 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
160 guest, but guarantees that the branch instruction will not be
161 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
162 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
163 complete inline asm, since it needs to be combined with more magic
164 inline asm stuff to be useful.
nethercotee90c6832004-10-18 18:07:49 +0000165*/
166
sewardj0ec07f32006-01-12 12:32:32 +0000167/* ---------------------------- x86 ---------------------------- */
sewardjde4a4ab2005-03-23 13:10:32 +0000168
sewardj0ec07f32006-01-12 12:32:32 +0000169#if defined(ARCH_x86)
sewardjc8858442006-01-20 15:17:20 +0000170
171typedef
172 struct {
173 unsigned int nraddr; /* where's the code? */
174 }
175 OrigFn;
176
sewardj0ec07f32006-01-12 12:32:32 +0000177#define __SPECIAL_INSTRUCTION_PREAMBLE \
178 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000179 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000180
sewardj0ec07f32006-01-12 12:32:32 +0000181#define VALGRIND_DO_CLIENT_REQUEST( \
182 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000183 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
184 { volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000185 volatile unsigned int _zzq_result; \
186 _zzq_args[0] = (unsigned int)(_zzq_request); \
187 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
188 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
189 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
190 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000191 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000192 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
193 /* %EDX = client_request ( %EAX ) */ \
194 "xchgl %%ebx,%%ebx" \
195 : "=d" (_zzq_result) \
196 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
197 : "cc", "memory" \
198 ); \
199 _zzq_rlval = _zzq_result; \
cerion85665ca2005-06-20 15:51:07 +0000200 }
sewardj2c48c7b2005-11-29 13:05:56 +0000201
sewardjc8858442006-01-20 15:17:20 +0000202#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
203 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
204 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000205 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
206 /* %EAX = guest_NRADDR */ \
207 "xchgl %%ecx,%%ecx" \
208 : "=a" (__addr) \
209 : \
210 : "cc", "memory" \
211 ); \
sewardjc8858442006-01-20 15:17:20 +0000212 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000213 }
sewardj0ec07f32006-01-12 12:32:32 +0000214
215#define VALGRIND_CALL_NOREDIR_EAX \
216 __SPECIAL_INSTRUCTION_PREAMBLE \
217 /* call-noredir *%EAX */ \
218 "xchgl %%edx,%%edx\n\t"
219#endif /* ARCH_x86 */
220
221/* --------------------------- amd64 --------------------------- */
222
223#if defined(ARCH_amd64)
sewardjc8858442006-01-20 15:17:20 +0000224
225typedef
226 struct {
227 unsigned long long int nraddr; /* where's the code? */
228 }
229 OrigFn;
230
sewardj0ec07f32006-01-12 12:32:32 +0000231#define __SPECIAL_INSTRUCTION_PREAMBLE \
232 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000233 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000234
235#define VALGRIND_DO_CLIENT_REQUEST( \
236 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000237 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
238 { volatile unsigned long long int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000239 volatile unsigned long long int _zzq_result; \
240 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
241 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
242 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
243 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
244 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000245 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000246 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
247 /* %RDX = client_request ( %RAX ) */ \
248 "xchgq %%rbx,%%rbx" \
249 : "=d" (_zzq_result) \
250 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
251 : "cc", "memory" \
252 ); \
253 _zzq_rlval = _zzq_result; \
254 }
255
sewardjc8858442006-01-20 15:17:20 +0000256#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
257 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
258 volatile unsigned long long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000259 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
260 /* %RAX = guest_NRADDR */ \
261 "xchgq %%rcx,%%rcx" \
262 : "=a" (__addr) \
263 : \
264 : "cc", "memory" \
265 ); \
sewardjc8858442006-01-20 15:17:20 +0000266 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000267 }
268
269#define VALGRIND_CALL_NOREDIR_RAX \
270 __SPECIAL_INSTRUCTION_PREAMBLE \
271 /* call-noredir *%RAX */ \
272 "xchgq %%rdx,%%rdx\n\t"
273#endif /* ARCH_amd64 */
274
275/* --------------------------- ppc32 --------------------------- */
276
277#if defined(ARCH_ppc32)
sewardjd68ac3e2006-01-20 14:31:57 +0000278
279typedef
280 struct {
sewardjc8858442006-01-20 15:17:20 +0000281 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000282 }
283 OrigFn;
284
sewardj0ec07f32006-01-12 12:32:32 +0000285#define __SPECIAL_INSTRUCTION_PREAMBLE \
286 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000287 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000288
289#define VALGRIND_DO_CLIENT_REQUEST( \
290 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000291 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000292 \
sewardj9af10a12006-02-01 14:59:42 +0000293 { unsigned int _zzq_args[6]; \
sewardj1a85f4f2006-01-12 21:15:35 +0000294 register unsigned int _zzq_result __asm__("r3"); \
295 register unsigned int* _zzq_ptr __asm__("r4"); \
sewardj0ec07f32006-01-12 12:32:32 +0000296 _zzq_args[0] = (unsigned int)(_zzq_request); \
297 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
298 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
299 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
300 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000301 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000302 _zzq_ptr = _zzq_args; \
303 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
304 /* %R3 = client_request ( %R4 ) */ \
305 "or 1,1,1" \
306 : "=r" (_zzq_result) \
307 : "0" (_zzq_default), "r" (_zzq_ptr) \
308 : "cc", "memory"); \
309 _zzq_rlval = _zzq_result; \
310 }
311
sewardjd68ac3e2006-01-20 14:31:57 +0000312#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
313 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
314 register unsigned int __addr __asm__("r3"); \
sewardj0ec07f32006-01-12 12:32:32 +0000315 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
316 /* %R3 = guest_NRADDR */ \
317 "or 2,2,2" \
318 : "=r" (__addr) \
319 : \
320 : "cc", "memory" \
321 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000322 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000323 }
324
325#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
326 __SPECIAL_INSTRUCTION_PREAMBLE \
327 /* branch-and-link-to-noredir *%R11 */ \
328 "or 3,3,3\n\t"
329#endif /* ARCH_ppc32 */
330
331/* --------------------------- ppc64 --------------------------- */
332
333#if defined(ARCH_ppc64)
sewardjd68ac3e2006-01-20 14:31:57 +0000334
335typedef
336 struct {
337 unsigned long long int nraddr; /* where's the code? */
338 unsigned long long int r2; /* what tocptr do we need? */
339 }
340 OrigFn;
341
sewardj1a85f4f2006-01-12 21:15:35 +0000342#define __SPECIAL_INSTRUCTION_PREAMBLE \
343 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
344 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
345
sewardj0ec07f32006-01-12 12:32:32 +0000346#define VALGRIND_DO_CLIENT_REQUEST( \
347 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000348 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000349 \
sewardj9af10a12006-02-01 14:59:42 +0000350 { unsigned long long int _zzq_args[6]; \
sewardj1a85f4f2006-01-12 21:15:35 +0000351 register unsigned long long int _zzq_result __asm__("r3"); \
352 register unsigned long long int* _zzq_ptr __asm__("r4"); \
353 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
354 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
355 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
356 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
357 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000358 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000359 _zzq_ptr = _zzq_args; \
sewardj1a85f4f2006-01-12 21:15:35 +0000360 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
361 /* %R3 = client_request ( %R4 ) */ \
362 "or 1,1,1" \
363 : "=r" (_zzq_result) \
sewardj0ec07f32006-01-12 12:32:32 +0000364 : "0" (_zzq_default), "r" (_zzq_ptr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000365 : "cc", "memory"); \
366 _zzq_rlval = _zzq_result; \
sewardj0ec07f32006-01-12 12:32:32 +0000367 }
sewardj1a85f4f2006-01-12 21:15:35 +0000368
sewardjd68ac3e2006-01-20 14:31:57 +0000369#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
370 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
371 register unsigned long long int __addr __asm__("r3"); \
sewardj1a85f4f2006-01-12 21:15:35 +0000372 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
373 /* %R3 = guest_NRADDR */ \
374 "or 2,2,2" \
375 : "=r" (__addr) \
376 : \
377 : "cc", "memory" \
378 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000379 _zzq_orig->nraddr = __addr; \
380 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
381 /* %R3 = guest_NRADDR_GPR2 */ \
382 "or 4,4,4" \
383 : "=r" (__addr) \
384 : \
385 : "cc", "memory" \
386 ); \
387 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000388 }
389
390#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
391 __SPECIAL_INSTRUCTION_PREAMBLE \
392 /* branch-and-link-to-noredir *%R11 */ \
393 "or 3,3,3\n\t"
394
sewardj0ec07f32006-01-12 12:32:32 +0000395#endif /* ARCH_ppc64 */
cerion85665ca2005-06-20 15:51:07 +0000396
njn3dd0a912005-06-28 19:44:10 +0000397/* Insert assembly code for other architectures here... */
njn26aba4d2005-05-16 13:31:23 +0000398
sewardj37091fb2002-11-16 11:06:50 +0000399#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +0000400
nethercote69d9c462004-10-26 13:00:12 +0000401
njn30d76c62005-06-18 15:07:39 +0000402/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000403/* ARCHITECTURE SPECIFICS for FUNCTION WRAPPING. This is all very */
404/* ugly. It's the least-worst tradeoff I can think of. */
405/* ------------------------------------------------------------------ */
406
407/* This section defines magic (a.k.a appalling-hack) macros for doing
408 guaranteed-no-redirection macros, so as to get from function
409 wrappers to the functions they are wrapping. The whole point is to
410 construct standard call sequences, but to do the call itself with a
411 special no-redirect call pseudo-instruction that the JIT
412 understands and handles specially. This section is long and
413 repetitious, and I can't see a way to make it shorter.
414
415 The naming scheme is as follows:
416
417 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
418
419 'W' stands for "word" and 'v' for "void". Hence there are
420 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
421 and for each, the possibility of returning a word-typed result, or
422 no result.
423*/
424
425/* Use these to write the name of your wrapper. NOTE: duplicates
426 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
427
428#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
429 _vgwZU_##soname##_##fnname
430
431#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
432 _vgwZZ_##soname##_##fnname
433
sewardjd68ac3e2006-01-20 14:31:57 +0000434/* Use this macro from within a wrapper function to collect the
435 context (address and possibly other info) of the original function.
436 Once you have that you can then use it in one of the CALL_FN_
437 macros. The type of the argument _lval is OrigFn. */
438#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +0000439
440/* Derivatives of the main macros below, for calling functions
441 returning void. */
442
443#define CALL_FN_v_v(fnptr) \
444 do { volatile unsigned long _junk; \
445 CALL_FN_W_v(_junk,fnptr); } while (0)
446
447#define CALL_FN_v_W(fnptr, arg1) \
448 do { volatile unsigned long _junk; \
449 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
450
451#define CALL_FN_v_WW(fnptr, arg1,arg2) \
452 do { volatile unsigned long _junk; \
453 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
454
sewardj5ce4b152006-03-11 12:57:41 +0000455#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
456 do { volatile unsigned long _junk; \
457 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
458
sewardj0ec07f32006-01-12 12:32:32 +0000459/* ---------------------------- x86 ---------------------------- */
460
461#if defined(ARCH_x86)
462
463/* These regs are trashed by the hidden call. No need to mention eax
464 as gcc can already see that, plus causes gcc to bomb. */
465#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
466
467/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
468 long) == 4. */
469
sewardj66226cc2006-01-20 15:46:46 +0000470#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +0000471 do { \
sewardj66226cc2006-01-20 15:46:46 +0000472 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000473 volatile unsigned long _argvec[1]; \
474 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000475 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000476 __asm__ volatile( \
477 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
478 VALGRIND_CALL_NOREDIR_EAX \
479 : /*out*/ "=a" (_res) \
480 : /*in*/ "a" (&_argvec[0]) \
481 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
482 ); \
483 lval = (__typeof__(lval)) _res; \
484 } while (0)
485
sewardj66226cc2006-01-20 15:46:46 +0000486#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +0000487 do { \
sewardj66226cc2006-01-20 15:46:46 +0000488 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000489 volatile unsigned long _argvec[2]; \
490 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000491 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000492 _argvec[1] = (unsigned long)(arg1); \
493 __asm__ volatile( \
494 "pushl 4(%%eax)\n\t" \
495 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
496 VALGRIND_CALL_NOREDIR_EAX \
497 "addl $4, %%esp\n" \
498 : /*out*/ "=a" (_res) \
499 : /*in*/ "a" (&_argvec[0]) \
500 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
501 ); \
502 lval = (__typeof__(lval)) _res; \
503 } while (0)
504
sewardj66226cc2006-01-20 15:46:46 +0000505#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +0000506 do { \
sewardj66226cc2006-01-20 15:46:46 +0000507 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000508 volatile unsigned long _argvec[3]; \
509 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000510 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000511 _argvec[1] = (unsigned long)(arg1); \
512 _argvec[2] = (unsigned long)(arg2); \
513 __asm__ volatile( \
514 "pushl 8(%%eax)\n\t" \
515 "pushl 4(%%eax)\n\t" \
516 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
517 VALGRIND_CALL_NOREDIR_EAX \
518 "addl $8, %%esp\n" \
519 : /*out*/ "=a" (_res) \
520 : /*in*/ "a" (&_argvec[0]) \
521 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
522 ); \
523 lval = (__typeof__(lval)) _res; \
524 } while (0)
525
sewardj9e8b07a2006-02-18 21:13:29 +0000526#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
527 do { \
528 volatile OrigFn _orig = (orig); \
529 volatile unsigned long _argvec[4]; \
530 volatile unsigned long _res; \
531 _argvec[0] = (unsigned long)_orig.nraddr; \
532 _argvec[1] = (unsigned long)(arg1); \
533 _argvec[2] = (unsigned long)(arg2); \
534 _argvec[3] = (unsigned long)(arg3); \
535 __asm__ volatile( \
536 "pushl 12(%%eax)\n\t" \
537 "pushl 8(%%eax)\n\t" \
538 "pushl 4(%%eax)\n\t" \
539 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
540 VALGRIND_CALL_NOREDIR_EAX \
541 "addl $12, %%esp\n" \
542 : /*out*/ "=a" (_res) \
543 : /*in*/ "a" (&_argvec[0]) \
544 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
545 ); \
546 lval = (__typeof__(lval)) _res; \
547 } while (0)
548
sewardj66226cc2006-01-20 15:46:46 +0000549#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
sewardj0ec07f32006-01-12 12:32:32 +0000550 do { \
sewardj66226cc2006-01-20 15:46:46 +0000551 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000552 volatile unsigned long _argvec[5]; \
553 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000554 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000555 _argvec[1] = (unsigned long)(arg1); \
556 _argvec[2] = (unsigned long)(arg2); \
557 _argvec[3] = (unsigned long)(arg3); \
558 _argvec[4] = (unsigned long)(arg4); \
559 __asm__ volatile( \
560 "pushl 16(%%eax)\n\t" \
561 "pushl 12(%%eax)\n\t" \
562 "pushl 8(%%eax)\n\t" \
563 "pushl 4(%%eax)\n\t" \
564 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
565 VALGRIND_CALL_NOREDIR_EAX \
566 "addl $16, %%esp\n" \
567 : /*out*/ "=a" (_res) \
568 : /*in*/ "a" (&_argvec[0]) \
569 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
570 ); \
571 lval = (__typeof__(lval)) _res; \
572 } while (0)
573
sewardj66226cc2006-01-20 15:46:46 +0000574#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000575 do { \
sewardj66226cc2006-01-20 15:46:46 +0000576 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000577 volatile unsigned long _argvec[6]; \
578 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000579 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000580 _argvec[1] = (unsigned long)(arg1); \
581 _argvec[2] = (unsigned long)(arg2); \
582 _argvec[3] = (unsigned long)(arg3); \
583 _argvec[4] = (unsigned long)(arg4); \
584 _argvec[5] = (unsigned long)(arg5); \
585 __asm__ volatile( \
586 "pushl 20(%%eax)\n\t" \
587 "pushl 16(%%eax)\n\t" \
588 "pushl 12(%%eax)\n\t" \
589 "pushl 8(%%eax)\n\t" \
590 "pushl 4(%%eax)\n\t" \
591 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
592 VALGRIND_CALL_NOREDIR_EAX \
593 "addl $20, %%esp\n" \
594 : /*out*/ "=a" (_res) \
595 : /*in*/ "a" (&_argvec[0]) \
596 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
597 ); \
598 lval = (__typeof__(lval)) _res; \
599 } while (0)
600
sewardj66226cc2006-01-20 15:46:46 +0000601#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +0000602 do { \
sewardj66226cc2006-01-20 15:46:46 +0000603 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000604 volatile unsigned long _argvec[7]; \
605 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000606 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000607 _argvec[1] = (unsigned long)(arg1); \
608 _argvec[2] = (unsigned long)(arg2); \
609 _argvec[3] = (unsigned long)(arg3); \
610 _argvec[4] = (unsigned long)(arg4); \
611 _argvec[5] = (unsigned long)(arg5); \
612 _argvec[6] = (unsigned long)(arg6); \
613 __asm__ volatile( \
614 "pushl 24(%%eax)\n\t" \
615 "pushl 20(%%eax)\n\t" \
616 "pushl 16(%%eax)\n\t" \
617 "pushl 12(%%eax)\n\t" \
618 "pushl 8(%%eax)\n\t" \
619 "pushl 4(%%eax)\n\t" \
620 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
621 VALGRIND_CALL_NOREDIR_EAX \
622 "addl $24, %%esp\n" \
623 : /*out*/ "=a" (_res) \
624 : /*in*/ "a" (&_argvec[0]) \
625 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
626 ); \
627 lval = (__typeof__(lval)) _res; \
628 } while (0)
629
sewardj66226cc2006-01-20 15:46:46 +0000630#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
631 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +0000632 do { \
sewardj66226cc2006-01-20 15:46:46 +0000633 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000634 volatile unsigned long _argvec[8]; \
635 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000636 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000637 _argvec[1] = (unsigned long)(arg1); \
638 _argvec[2] = (unsigned long)(arg2); \
639 _argvec[3] = (unsigned long)(arg3); \
640 _argvec[4] = (unsigned long)(arg4); \
641 _argvec[5] = (unsigned long)(arg5); \
642 _argvec[6] = (unsigned long)(arg6); \
643 _argvec[7] = (unsigned long)(arg7); \
644 __asm__ volatile( \
645 "pushl 28(%%eax)\n\t" \
646 "pushl 24(%%eax)\n\t" \
647 "pushl 20(%%eax)\n\t" \
648 "pushl 16(%%eax)\n\t" \
649 "pushl 12(%%eax)\n\t" \
650 "pushl 8(%%eax)\n\t" \
651 "pushl 4(%%eax)\n\t" \
652 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
653 VALGRIND_CALL_NOREDIR_EAX \
654 "addl $28, %%esp\n" \
655 : /*out*/ "=a" (_res) \
656 : /*in*/ "a" (&_argvec[0]) \
657 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
658 ); \
659 lval = (__typeof__(lval)) _res; \
660 } while (0)
661
sewardj66226cc2006-01-20 15:46:46 +0000662#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
663 arg7,arg8) \
sewardj0ec07f32006-01-12 12:32:32 +0000664 do { \
sewardj66226cc2006-01-20 15:46:46 +0000665 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000666 volatile unsigned long _argvec[9]; \
667 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000668 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000669 _argvec[1] = (unsigned long)(arg1); \
670 _argvec[2] = (unsigned long)(arg2); \
671 _argvec[3] = (unsigned long)(arg3); \
672 _argvec[4] = (unsigned long)(arg4); \
673 _argvec[5] = (unsigned long)(arg5); \
674 _argvec[6] = (unsigned long)(arg6); \
675 _argvec[7] = (unsigned long)(arg7); \
676 _argvec[8] = (unsigned long)(arg8); \
677 __asm__ volatile( \
678 "pushl 32(%%eax)\n\t" \
679 "pushl 28(%%eax)\n\t" \
680 "pushl 24(%%eax)\n\t" \
681 "pushl 20(%%eax)\n\t" \
682 "pushl 16(%%eax)\n\t" \
683 "pushl 12(%%eax)\n\t" \
684 "pushl 8(%%eax)\n\t" \
685 "pushl 4(%%eax)\n\t" \
686 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
687 VALGRIND_CALL_NOREDIR_EAX \
688 "addl $32, %%esp\n" \
689 : /*out*/ "=a" (_res) \
690 : /*in*/ "a" (&_argvec[0]) \
691 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
692 ); \
693 lval = (__typeof__(lval)) _res; \
694 } while (0)
695
sewardj45fa5b02006-03-09 19:06:23 +0000696#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
697 arg7,arg8,arg9) \
698 do { \
699 volatile OrigFn _orig = (orig); \
700 volatile unsigned long _argvec[10]; \
701 volatile unsigned long _res; \
702 _argvec[0] = (unsigned long)_orig.nraddr; \
703 _argvec[1] = (unsigned long)(arg1); \
704 _argvec[2] = (unsigned long)(arg2); \
705 _argvec[3] = (unsigned long)(arg3); \
706 _argvec[4] = (unsigned long)(arg4); \
707 _argvec[5] = (unsigned long)(arg5); \
708 _argvec[6] = (unsigned long)(arg6); \
709 _argvec[7] = (unsigned long)(arg7); \
710 _argvec[8] = (unsigned long)(arg8); \
711 _argvec[9] = (unsigned long)(arg9); \
712 __asm__ volatile( \
713 "pushl 36(%%eax)\n\t" \
714 "pushl 32(%%eax)\n\t" \
715 "pushl 28(%%eax)\n\t" \
716 "pushl 24(%%eax)\n\t" \
717 "pushl 20(%%eax)\n\t" \
718 "pushl 16(%%eax)\n\t" \
719 "pushl 12(%%eax)\n\t" \
720 "pushl 8(%%eax)\n\t" \
721 "pushl 4(%%eax)\n\t" \
722 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
723 VALGRIND_CALL_NOREDIR_EAX \
724 "addl $36, %%esp\n" \
725 : /*out*/ "=a" (_res) \
726 : /*in*/ "a" (&_argvec[0]) \
727 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
728 ); \
729 lval = (__typeof__(lval)) _res; \
730 } while (0)
731
732#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
733 arg7,arg8,arg9,arg10) \
734 do { \
735 volatile OrigFn _orig = (orig); \
736 volatile unsigned long _argvec[11]; \
737 volatile unsigned long _res; \
738 _argvec[0] = (unsigned long)_orig.nraddr; \
739 _argvec[1] = (unsigned long)(arg1); \
740 _argvec[2] = (unsigned long)(arg2); \
741 _argvec[3] = (unsigned long)(arg3); \
742 _argvec[4] = (unsigned long)(arg4); \
743 _argvec[5] = (unsigned long)(arg5); \
744 _argvec[6] = (unsigned long)(arg6); \
745 _argvec[7] = (unsigned long)(arg7); \
746 _argvec[8] = (unsigned long)(arg8); \
747 _argvec[9] = (unsigned long)(arg9); \
748 _argvec[10] = (unsigned long)(arg10); \
749 __asm__ volatile( \
750 "pushl 40(%%eax)\n\t" \
751 "pushl 36(%%eax)\n\t" \
752 "pushl 32(%%eax)\n\t" \
753 "pushl 28(%%eax)\n\t" \
754 "pushl 24(%%eax)\n\t" \
755 "pushl 20(%%eax)\n\t" \
756 "pushl 16(%%eax)\n\t" \
757 "pushl 12(%%eax)\n\t" \
758 "pushl 8(%%eax)\n\t" \
759 "pushl 4(%%eax)\n\t" \
760 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
761 VALGRIND_CALL_NOREDIR_EAX \
762 "addl $40, %%esp\n" \
763 : /*out*/ "=a" (_res) \
764 : /*in*/ "a" (&_argvec[0]) \
765 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
766 ); \
767 lval = (__typeof__(lval)) _res; \
768 } while (0)
769
sewardj5ce4b152006-03-11 12:57:41 +0000770#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
771 arg6,arg7,arg8,arg9,arg10, \
772 arg11) \
773 do { \
774 volatile OrigFn _orig = (orig); \
775 volatile unsigned long _argvec[12]; \
776 volatile unsigned long _res; \
777 _argvec[0] = (unsigned long)_orig.nraddr; \
778 _argvec[1] = (unsigned long)(arg1); \
779 _argvec[2] = (unsigned long)(arg2); \
780 _argvec[3] = (unsigned long)(arg3); \
781 _argvec[4] = (unsigned long)(arg4); \
782 _argvec[5] = (unsigned long)(arg5); \
783 _argvec[6] = (unsigned long)(arg6); \
784 _argvec[7] = (unsigned long)(arg7); \
785 _argvec[8] = (unsigned long)(arg8); \
786 _argvec[9] = (unsigned long)(arg9); \
787 _argvec[10] = (unsigned long)(arg10); \
788 _argvec[11] = (unsigned long)(arg11); \
789 __asm__ volatile( \
790 "pushl 44(%%eax)\n\t" \
791 "pushl 40(%%eax)\n\t" \
792 "pushl 36(%%eax)\n\t" \
793 "pushl 32(%%eax)\n\t" \
794 "pushl 28(%%eax)\n\t" \
795 "pushl 24(%%eax)\n\t" \
796 "pushl 20(%%eax)\n\t" \
797 "pushl 16(%%eax)\n\t" \
798 "pushl 12(%%eax)\n\t" \
799 "pushl 8(%%eax)\n\t" \
800 "pushl 4(%%eax)\n\t" \
801 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
802 VALGRIND_CALL_NOREDIR_EAX \
803 "addl $44, %%esp\n" \
804 : /*out*/ "=a" (_res) \
805 : /*in*/ "a" (&_argvec[0]) \
806 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
807 ); \
808 lval = (__typeof__(lval)) _res; \
809 } while (0)
810
sewardj66226cc2006-01-20 15:46:46 +0000811#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
812 arg6,arg7,arg8,arg9,arg10, \
813 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +0000814 do { \
sewardj66226cc2006-01-20 15:46:46 +0000815 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000816 volatile unsigned long _argvec[13]; \
817 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000818 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000819 _argvec[1] = (unsigned long)(arg1); \
820 _argvec[2] = (unsigned long)(arg2); \
821 _argvec[3] = (unsigned long)(arg3); \
822 _argvec[4] = (unsigned long)(arg4); \
823 _argvec[5] = (unsigned long)(arg5); \
824 _argvec[6] = (unsigned long)(arg6); \
825 _argvec[7] = (unsigned long)(arg7); \
826 _argvec[8] = (unsigned long)(arg8); \
827 _argvec[9] = (unsigned long)(arg9); \
828 _argvec[10] = (unsigned long)(arg10); \
829 _argvec[11] = (unsigned long)(arg11); \
830 _argvec[12] = (unsigned long)(arg12); \
831 __asm__ volatile( \
832 "pushl 48(%%eax)\n\t" \
833 "pushl 44(%%eax)\n\t" \
834 "pushl 40(%%eax)\n\t" \
835 "pushl 36(%%eax)\n\t" \
836 "pushl 32(%%eax)\n\t" \
837 "pushl 28(%%eax)\n\t" \
838 "pushl 24(%%eax)\n\t" \
839 "pushl 20(%%eax)\n\t" \
840 "pushl 16(%%eax)\n\t" \
841 "pushl 12(%%eax)\n\t" \
842 "pushl 8(%%eax)\n\t" \
843 "pushl 4(%%eax)\n\t" \
844 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
845 VALGRIND_CALL_NOREDIR_EAX \
846 "addl $48, %%esp\n" \
847 : /*out*/ "=a" (_res) \
848 : /*in*/ "a" (&_argvec[0]) \
849 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
850 ); \
851 lval = (__typeof__(lval)) _res; \
852 } while (0)
853
854#endif /* ARCH_x86 */
855
856/* --------------------------- amd64 --------------------------- */
857
858#if defined(ARCH_amd64)
859
860/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
861
862/* These regs are trashed by the hidden call. */
863#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
864 "rdi", "r8", "r9", "r10", "r11"
865
866/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
867 long) == 8. */
868
sewardjc8858442006-01-20 15:17:20 +0000869#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +0000870 do { \
sewardjc8858442006-01-20 15:17:20 +0000871 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000872 volatile unsigned long _argvec[1]; \
873 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +0000874 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000875 __asm__ volatile( \
876 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
877 VALGRIND_CALL_NOREDIR_RAX \
878 : /*out*/ "=a" (_res) \
879 : /*in*/ "a" (&_argvec[0]) \
880 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
881 ); \
882 lval = (__typeof__(lval)) _res; \
883 } while (0)
884
sewardjc8858442006-01-20 15:17:20 +0000885#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +0000886 do { \
sewardjc8858442006-01-20 15:17:20 +0000887 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000888 volatile unsigned long _argvec[2]; \
889 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +0000890 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000891 _argvec[1] = (unsigned long)(arg1); \
892 __asm__ volatile( \
893 "movq 8(%%rax), %%rdi\n\t" \
894 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
895 VALGRIND_CALL_NOREDIR_RAX \
896 : /*out*/ "=a" (_res) \
897 : /*in*/ "a" (&_argvec[0]) \
898 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
899 ); \
900 lval = (__typeof__(lval)) _res; \
901 } while (0)
902
sewardjc8858442006-01-20 15:17:20 +0000903#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +0000904 do { \
sewardjc8858442006-01-20 15:17:20 +0000905 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000906 volatile unsigned long _argvec[3]; \
907 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +0000908 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000909 _argvec[1] = (unsigned long)(arg1); \
910 _argvec[2] = (unsigned long)(arg2); \
911 __asm__ volatile( \
912 "movq 16(%%rax), %%rsi\n\t" \
913 "movq 8(%%rax), %%rdi\n\t" \
914 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
915 VALGRIND_CALL_NOREDIR_RAX \
916 : /*out*/ "=a" (_res) \
917 : /*in*/ "a" (&_argvec[0]) \
918 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
919 ); \
920 lval = (__typeof__(lval)) _res; \
921 } while (0)
922
sewardja50f9dc2006-03-11 16:19:14 +0000923#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
924 do { \
925 volatile OrigFn _orig = (orig); \
926 volatile unsigned long _argvec[4]; \
927 volatile unsigned long _res; \
928 _argvec[0] = (unsigned long)_orig.nraddr; \
929 _argvec[1] = (unsigned long)(arg1); \
930 _argvec[2] = (unsigned long)(arg2); \
931 _argvec[3] = (unsigned long)(arg3); \
932 __asm__ volatile( \
933 "movq 24(%%rax), %%rdx\n\t" \
934 "movq 16(%%rax), %%rsi\n\t" \
935 "movq 8(%%rax), %%rdi\n\t" \
936 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
937 VALGRIND_CALL_NOREDIR_RAX \
938 : /*out*/ "=a" (_res) \
939 : /*in*/ "a" (&_argvec[0]) \
940 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
941 ); \
942 lval = (__typeof__(lval)) _res; \
943 } while (0)
944
945#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
946 do { \
947 volatile OrigFn _orig = (orig); \
948 volatile unsigned long _argvec[5]; \
949 volatile unsigned long _res; \
950 _argvec[0] = (unsigned long)_orig.nraddr; \
951 _argvec[1] = (unsigned long)(arg1); \
952 _argvec[2] = (unsigned long)(arg2); \
953 _argvec[3] = (unsigned long)(arg3); \
954 _argvec[4] = (unsigned long)(arg4); \
955 __asm__ volatile( \
956 "movq 32(%%rax), %%rcx\n\t" \
957 "movq 24(%%rax), %%rdx\n\t" \
958 "movq 16(%%rax), %%rsi\n\t" \
959 "movq 8(%%rax), %%rdi\n\t" \
960 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
961 VALGRIND_CALL_NOREDIR_RAX \
962 : /*out*/ "=a" (_res) \
963 : /*in*/ "a" (&_argvec[0]) \
964 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
965 ); \
966 lval = (__typeof__(lval)) _res; \
967 } while (0)
968
969#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
970 do { \
971 volatile OrigFn _orig = (orig); \
972 volatile unsigned long _argvec[6]; \
973 volatile unsigned long _res; \
974 _argvec[0] = (unsigned long)_orig.nraddr; \
975 _argvec[1] = (unsigned long)(arg1); \
976 _argvec[2] = (unsigned long)(arg2); \
977 _argvec[3] = (unsigned long)(arg3); \
978 _argvec[4] = (unsigned long)(arg4); \
979 _argvec[5] = (unsigned long)(arg5); \
980 __asm__ volatile( \
981 "movq 40(%%rax), %%r8\n\t" \
982 "movq 32(%%rax), %%rcx\n\t" \
983 "movq 24(%%rax), %%rdx\n\t" \
984 "movq 16(%%rax), %%rsi\n\t" \
985 "movq 8(%%rax), %%rdi\n\t" \
986 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
987 VALGRIND_CALL_NOREDIR_RAX \
988 : /*out*/ "=a" (_res) \
989 : /*in*/ "a" (&_argvec[0]) \
990 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
991 ); \
992 lval = (__typeof__(lval)) _res; \
993 } while (0)
994
995#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
996 do { \
997 volatile OrigFn _orig = (orig); \
998 volatile unsigned long _argvec[7]; \
999 volatile unsigned long _res; \
1000 _argvec[0] = (unsigned long)_orig.nraddr; \
1001 _argvec[1] = (unsigned long)(arg1); \
1002 _argvec[2] = (unsigned long)(arg2); \
1003 _argvec[3] = (unsigned long)(arg3); \
1004 _argvec[4] = (unsigned long)(arg4); \
1005 _argvec[5] = (unsigned long)(arg5); \
1006 _argvec[6] = (unsigned long)(arg6); \
1007 __asm__ volatile( \
1008 "movq 48(%%rax), %%r9\n\t" \
1009 "movq 40(%%rax), %%r8\n\t" \
1010 "movq 32(%%rax), %%rcx\n\t" \
1011 "movq 24(%%rax), %%rdx\n\t" \
1012 "movq 16(%%rax), %%rsi\n\t" \
1013 "movq 8(%%rax), %%rdi\n\t" \
1014 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1015 VALGRIND_CALL_NOREDIR_RAX \
1016 : /*out*/ "=a" (_res) \
1017 : /*in*/ "a" (&_argvec[0]) \
1018 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1019 ); \
1020 lval = (__typeof__(lval)) _res; \
1021 } while (0)
1022
1023#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1024 arg7) \
1025 do { \
1026 volatile OrigFn _orig = (orig); \
1027 volatile unsigned long _argvec[8]; \
1028 volatile unsigned long _res; \
1029 _argvec[0] = (unsigned long)_orig.nraddr; \
1030 _argvec[1] = (unsigned long)(arg1); \
1031 _argvec[2] = (unsigned long)(arg2); \
1032 _argvec[3] = (unsigned long)(arg3); \
1033 _argvec[4] = (unsigned long)(arg4); \
1034 _argvec[5] = (unsigned long)(arg5); \
1035 _argvec[6] = (unsigned long)(arg6); \
1036 _argvec[7] = (unsigned long)(arg7); \
1037 __asm__ volatile( \
1038 "pushq 56(%%rax)\n\t" \
1039 "movq 48(%%rax), %%r9\n\t" \
1040 "movq 40(%%rax), %%r8\n\t" \
1041 "movq 32(%%rax), %%rcx\n\t" \
1042 "movq 24(%%rax), %%rdx\n\t" \
1043 "movq 16(%%rax), %%rsi\n\t" \
1044 "movq 8(%%rax), %%rdi\n\t" \
1045 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1046 VALGRIND_CALL_NOREDIR_RAX \
1047 "addq $8, %%rsp\n" \
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
1055#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1056 arg7,arg8) \
1057 do { \
1058 volatile OrigFn _orig = (orig); \
1059 volatile unsigned long _argvec[9]; \
1060 volatile unsigned long _res; \
1061 _argvec[0] = (unsigned long)_orig.nraddr; \
1062 _argvec[1] = (unsigned long)(arg1); \
1063 _argvec[2] = (unsigned long)(arg2); \
1064 _argvec[3] = (unsigned long)(arg3); \
1065 _argvec[4] = (unsigned long)(arg4); \
1066 _argvec[5] = (unsigned long)(arg5); \
1067 _argvec[6] = (unsigned long)(arg6); \
1068 _argvec[7] = (unsigned long)(arg7); \
1069 _argvec[8] = (unsigned long)(arg8); \
1070 __asm__ volatile( \
1071 "pushq 64(%%rax)\n\t" \
1072 "pushq 56(%%rax)\n\t" \
1073 "movq 48(%%rax), %%r9\n\t" \
1074 "movq 40(%%rax), %%r8\n\t" \
1075 "movq 32(%%rax), %%rcx\n\t" \
1076 "movq 24(%%rax), %%rdx\n\t" \
1077 "movq 16(%%rax), %%rsi\n\t" \
1078 "movq 8(%%rax), %%rdi\n\t" \
1079 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1080 VALGRIND_CALL_NOREDIR_RAX \
1081 "addq $16, %%rsp\n" \
1082 : /*out*/ "=a" (_res) \
1083 : /*in*/ "a" (&_argvec[0]) \
1084 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1085 ); \
1086 lval = (__typeof__(lval)) _res; \
1087 } while (0)
1088
1089#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1090 arg7,arg8,arg9) \
1091 do { \
1092 volatile OrigFn _orig = (orig); \
1093 volatile unsigned long _argvec[10]; \
1094 volatile unsigned long _res; \
1095 _argvec[0] = (unsigned long)_orig.nraddr; \
1096 _argvec[1] = (unsigned long)(arg1); \
1097 _argvec[2] = (unsigned long)(arg2); \
1098 _argvec[3] = (unsigned long)(arg3); \
1099 _argvec[4] = (unsigned long)(arg4); \
1100 _argvec[5] = (unsigned long)(arg5); \
1101 _argvec[6] = (unsigned long)(arg6); \
1102 _argvec[7] = (unsigned long)(arg7); \
1103 _argvec[8] = (unsigned long)(arg8); \
1104 _argvec[9] = (unsigned long)(arg9); \
1105 __asm__ volatile( \
1106 "pushq 72(%%rax)\n\t" \
1107 "pushq 64(%%rax)\n\t" \
1108 "pushq 56(%%rax)\n\t" \
1109 "movq 48(%%rax), %%r9\n\t" \
1110 "movq 40(%%rax), %%r8\n\t" \
1111 "movq 32(%%rax), %%rcx\n\t" \
1112 "movq 24(%%rax), %%rdx\n\t" \
1113 "movq 16(%%rax), %%rsi\n\t" \
1114 "movq 8(%%rax), %%rdi\n\t" \
1115 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1116 VALGRIND_CALL_NOREDIR_RAX \
1117 "addq $24, %%rsp\n" \
1118 : /*out*/ "=a" (_res) \
1119 : /*in*/ "a" (&_argvec[0]) \
1120 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1121 ); \
1122 lval = (__typeof__(lval)) _res; \
1123 } while (0)
1124
1125#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1126 arg7,arg8,arg9,arg10) \
1127 do { \
1128 volatile OrigFn _orig = (orig); \
1129 volatile unsigned long _argvec[11]; \
1130 volatile unsigned long _res; \
1131 _argvec[0] = (unsigned long)_orig.nraddr; \
1132 _argvec[1] = (unsigned long)(arg1); \
1133 _argvec[2] = (unsigned long)(arg2); \
1134 _argvec[3] = (unsigned long)(arg3); \
1135 _argvec[4] = (unsigned long)(arg4); \
1136 _argvec[5] = (unsigned long)(arg5); \
1137 _argvec[6] = (unsigned long)(arg6); \
1138 _argvec[7] = (unsigned long)(arg7); \
1139 _argvec[8] = (unsigned long)(arg8); \
1140 _argvec[9] = (unsigned long)(arg9); \
1141 _argvec[10] = (unsigned long)(arg10); \
1142 __asm__ volatile( \
1143 "pushq 80(%%rax)\n\t" \
1144 "pushq 72(%%rax)\n\t" \
1145 "pushq 64(%%rax)\n\t" \
1146 "pushq 56(%%rax)\n\t" \
1147 "movq 48(%%rax), %%r9\n\t" \
1148 "movq 40(%%rax), %%r8\n\t" \
1149 "movq 32(%%rax), %%rcx\n\t" \
1150 "movq 24(%%rax), %%rdx\n\t" \
1151 "movq 16(%%rax), %%rsi\n\t" \
1152 "movq 8(%%rax), %%rdi\n\t" \
1153 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1154 VALGRIND_CALL_NOREDIR_RAX \
1155 "addq $32, %%rsp\n" \
1156 : /*out*/ "=a" (_res) \
1157 : /*in*/ "a" (&_argvec[0]) \
1158 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1159 ); \
1160 lval = (__typeof__(lval)) _res; \
1161 } while (0)
1162
1163#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1164 arg7,arg8,arg9,arg10,arg11) \
1165 do { \
1166 volatile OrigFn _orig = (orig); \
1167 volatile unsigned long _argvec[12]; \
1168 volatile unsigned long _res; \
1169 _argvec[0] = (unsigned long)_orig.nraddr; \
1170 _argvec[1] = (unsigned long)(arg1); \
1171 _argvec[2] = (unsigned long)(arg2); \
1172 _argvec[3] = (unsigned long)(arg3); \
1173 _argvec[4] = (unsigned long)(arg4); \
1174 _argvec[5] = (unsigned long)(arg5); \
1175 _argvec[6] = (unsigned long)(arg6); \
1176 _argvec[7] = (unsigned long)(arg7); \
1177 _argvec[8] = (unsigned long)(arg8); \
1178 _argvec[9] = (unsigned long)(arg9); \
1179 _argvec[10] = (unsigned long)(arg10); \
1180 _argvec[11] = (unsigned long)(arg11); \
1181 __asm__ volatile( \
1182 "pushq 88(%%rax)\n\t" \
1183 "pushq 80(%%rax)\n\t" \
1184 "pushq 72(%%rax)\n\t" \
1185 "pushq 64(%%rax)\n\t" \
1186 "pushq 56(%%rax)\n\t" \
1187 "movq 48(%%rax), %%r9\n\t" \
1188 "movq 40(%%rax), %%r8\n\t" \
1189 "movq 32(%%rax), %%rcx\n\t" \
1190 "movq 24(%%rax), %%rdx\n\t" \
1191 "movq 16(%%rax), %%rsi\n\t" \
1192 "movq 8(%%rax), %%rdi\n\t" \
1193 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1194 VALGRIND_CALL_NOREDIR_RAX \
1195 "addq $40, %%rsp\n" \
1196 : /*out*/ "=a" (_res) \
1197 : /*in*/ "a" (&_argvec[0]) \
1198 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1199 ); \
1200 lval = (__typeof__(lval)) _res; \
1201 } while (0)
1202
1203#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1204 arg7,arg8,arg9,arg10,arg11,arg12) \
1205 do { \
1206 volatile OrigFn _orig = (orig); \
1207 volatile unsigned long _argvec[13]; \
1208 volatile unsigned long _res; \
1209 _argvec[0] = (unsigned long)_orig.nraddr; \
1210 _argvec[1] = (unsigned long)(arg1); \
1211 _argvec[2] = (unsigned long)(arg2); \
1212 _argvec[3] = (unsigned long)(arg3); \
1213 _argvec[4] = (unsigned long)(arg4); \
1214 _argvec[5] = (unsigned long)(arg5); \
1215 _argvec[6] = (unsigned long)(arg6); \
1216 _argvec[7] = (unsigned long)(arg7); \
1217 _argvec[8] = (unsigned long)(arg8); \
1218 _argvec[9] = (unsigned long)(arg9); \
1219 _argvec[10] = (unsigned long)(arg10); \
1220 _argvec[11] = (unsigned long)(arg11); \
1221 _argvec[12] = (unsigned long)(arg12); \
1222 __asm__ volatile( \
1223 "pushq 96(%%rax)\n\t" \
1224 "pushq 88(%%rax)\n\t" \
1225 "pushq 80(%%rax)\n\t" \
1226 "pushq 72(%%rax)\n\t" \
1227 "pushq 64(%%rax)\n\t" \
1228 "pushq 56(%%rax)\n\t" \
1229 "movq 48(%%rax), %%r9\n\t" \
1230 "movq 40(%%rax), %%r8\n\t" \
1231 "movq 32(%%rax), %%rcx\n\t" \
1232 "movq 24(%%rax), %%rdx\n\t" \
1233 "movq 16(%%rax), %%rsi\n\t" \
1234 "movq 8(%%rax), %%rdi\n\t" \
1235 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1236 VALGRIND_CALL_NOREDIR_RAX \
1237 "addq $48, %%rsp\n" \
1238 : /*out*/ "=a" (_res) \
1239 : /*in*/ "a" (&_argvec[0]) \
1240 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1241 ); \
1242 lval = (__typeof__(lval)) _res; \
1243 } while (0)
1244
sewardj0ec07f32006-01-12 12:32:32 +00001245#endif /* ARCH_amd64 */
1246
1247/* --------------------------- ppc32 --------------------------- */
1248
1249#if defined(ARCH_ppc32)
1250
sewardjead61df2006-03-12 13:39:15 +00001251/* This is useful for finding out about the on-stack stuff:
1252
1253 extern int f9 ( int,int,int,int,int,int,int,int,int );
1254 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1255 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1256 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1257
1258 int g9 ( void ) {
1259 return f9(11,22,33,44,55,66,77,88,99);
1260 }
1261 int g10 ( void ) {
1262 return f10(11,22,33,44,55,66,77,88,99,110);
1263 }
1264 int g11 ( void ) {
1265 return f11(11,22,33,44,55,66,77,88,99,110,121);
1266 }
1267 int g12 ( void ) {
1268 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1269 }
1270*/
1271
sewardj0ec07f32006-01-12 12:32:32 +00001272/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1273
1274/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00001275#define __CALLER_SAVED_REGS \
1276 "lr", "ctr", "xer", \
1277 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1278 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1279 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00001280
sewardjead61df2006-03-12 13:39:15 +00001281/* These CALL_FN_ macros assume that on ppc32-linux,
1282 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00001283
sewardj38de0992006-01-20 16:46:34 +00001284#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001285 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001286 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001287 volatile unsigned long _argvec[1]; \
1288 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001289 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001290 __asm__ volatile( \
1291 "mr 11,%1\n\t" \
1292 "lwz 11,0(11)\n\t" /* target->r11 */ \
1293 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1294 "mr %0,3" \
1295 : /*out*/ "=r" (_res) \
1296 : /*in*/ "r" (&_argvec[0]) \
1297 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1298 ); \
1299 lval = (__typeof__(lval)) _res; \
1300 } while (0)
1301
sewardj38de0992006-01-20 16:46:34 +00001302#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001303 do { \
sewardj38de0992006-01-20 16:46:34 +00001304 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001305 volatile unsigned long _argvec[2]; \
1306 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001307 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001308 _argvec[1] = (unsigned long)arg1; \
1309 __asm__ volatile( \
1310 "mr 11,%1\n\t" \
1311 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1312 "lwz 11,0(11)\n\t" /* target->r11 */ \
1313 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1314 "mr %0,3" \
1315 : /*out*/ "=r" (_res) \
1316 : /*in*/ "r" (&_argvec[0]) \
1317 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1318 ); \
1319 lval = (__typeof__(lval)) _res; \
1320 } while (0)
1321
sewardj38de0992006-01-20 16:46:34 +00001322#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001323 do { \
sewardj38de0992006-01-20 16:46:34 +00001324 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001325 volatile unsigned long _argvec[3]; \
1326 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001327 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001328 _argvec[1] = (unsigned long)arg1; \
1329 _argvec[2] = (unsigned long)arg2; \
1330 __asm__ volatile( \
1331 "mr 11,%1\n\t" \
1332 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1333 "lwz 4,8(11)\n\t" \
1334 "lwz 11,0(11)\n\t" /* target->r11 */ \
1335 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1336 "mr %0,3" \
1337 : /*out*/ "=r" (_res) \
1338 : /*in*/ "r" (&_argvec[0]) \
1339 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1340 ); \
1341 lval = (__typeof__(lval)) _res; \
1342 } while (0)
1343
sewardjead61df2006-03-12 13:39:15 +00001344#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1345 do { \
1346 volatile OrigFn _orig = (orig); \
1347 volatile unsigned long _argvec[4]; \
1348 volatile unsigned long _res; \
1349 _argvec[0] = (unsigned long)_orig.nraddr; \
1350 _argvec[1] = (unsigned long)arg1; \
1351 _argvec[2] = (unsigned long)arg2; \
1352 _argvec[3] = (unsigned long)arg3; \
1353 __asm__ volatile( \
1354 "mr 11,%1\n\t" \
1355 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1356 "lwz 4,8(11)\n\t" \
1357 "lwz 5,12(11)\n\t" \
1358 "lwz 11,0(11)\n\t" /* target->r11 */ \
1359 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1360 "mr %0,3" \
1361 : /*out*/ "=r" (_res) \
1362 : /*in*/ "r" (&_argvec[0]) \
1363 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1364 ); \
1365 lval = (__typeof__(lval)) _res; \
1366 } while (0)
1367
1368#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1369 do { \
1370 volatile OrigFn _orig = (orig); \
1371 volatile unsigned long _argvec[5]; \
1372 volatile unsigned long _res; \
1373 _argvec[0] = (unsigned long)_orig.nraddr; \
1374 _argvec[1] = (unsigned long)arg1; \
1375 _argvec[2] = (unsigned long)arg2; \
1376 _argvec[3] = (unsigned long)arg3; \
1377 _argvec[4] = (unsigned long)arg4; \
1378 __asm__ volatile( \
1379 "mr 11,%1\n\t" \
1380 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1381 "lwz 4,8(11)\n\t" \
1382 "lwz 5,12(11)\n\t" \
1383 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1384 "lwz 11,0(11)\n\t" /* target->r11 */ \
1385 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1386 "mr %0,3" \
1387 : /*out*/ "=r" (_res) \
1388 : /*in*/ "r" (&_argvec[0]) \
1389 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1390 ); \
1391 lval = (__typeof__(lval)) _res; \
1392 } while (0)
1393
1394#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1395 do { \
1396 volatile OrigFn _orig = (orig); \
1397 volatile unsigned long _argvec[6]; \
1398 volatile unsigned long _res; \
1399 _argvec[0] = (unsigned long)_orig.nraddr; \
1400 _argvec[1] = (unsigned long)arg1; \
1401 _argvec[2] = (unsigned long)arg2; \
1402 _argvec[3] = (unsigned long)arg3; \
1403 _argvec[4] = (unsigned long)arg4; \
1404 _argvec[5] = (unsigned long)arg5; \
1405 __asm__ volatile( \
1406 "mr 11,%1\n\t" \
1407 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1408 "lwz 4,8(11)\n\t" \
1409 "lwz 5,12(11)\n\t" \
1410 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1411 "lwz 7,20(11)\n\t" \
1412 "lwz 11,0(11)\n\t" /* target->r11 */ \
1413 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1414 "mr %0,3" \
1415 : /*out*/ "=r" (_res) \
1416 : /*in*/ "r" (&_argvec[0]) \
1417 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1418 ); \
1419 lval = (__typeof__(lval)) _res; \
1420 } while (0)
1421
1422#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1423 do { \
1424 volatile OrigFn _orig = (orig); \
1425 volatile unsigned long _argvec[7]; \
1426 volatile unsigned long _res; \
1427 _argvec[0] = (unsigned long)_orig.nraddr; \
1428 _argvec[1] = (unsigned long)arg1; \
1429 _argvec[2] = (unsigned long)arg2; \
1430 _argvec[3] = (unsigned long)arg3; \
1431 _argvec[4] = (unsigned long)arg4; \
1432 _argvec[5] = (unsigned long)arg5; \
1433 _argvec[6] = (unsigned long)arg6; \
1434 __asm__ volatile( \
1435 "mr 11,%1\n\t" \
1436 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1437 "lwz 4,8(11)\n\t" \
1438 "lwz 5,12(11)\n\t" \
1439 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1440 "lwz 7,20(11)\n\t" \
1441 "lwz 8,24(11)\n\t" \
1442 "lwz 11,0(11)\n\t" /* target->r11 */ \
1443 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1444 "mr %0,3" \
1445 : /*out*/ "=r" (_res) \
1446 : /*in*/ "r" (&_argvec[0]) \
1447 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1448 ); \
1449 lval = (__typeof__(lval)) _res; \
1450 } while (0)
1451
1452#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1453 arg7) \
1454 do { \
1455 volatile OrigFn _orig = (orig); \
1456 volatile unsigned long _argvec[8]; \
1457 volatile unsigned long _res; \
1458 _argvec[0] = (unsigned long)_orig.nraddr; \
1459 _argvec[1] = (unsigned long)arg1; \
1460 _argvec[2] = (unsigned long)arg2; \
1461 _argvec[3] = (unsigned long)arg3; \
1462 _argvec[4] = (unsigned long)arg4; \
1463 _argvec[5] = (unsigned long)arg5; \
1464 _argvec[6] = (unsigned long)arg6; \
1465 _argvec[7] = (unsigned long)arg7; \
1466 __asm__ volatile( \
1467 "mr 11,%1\n\t" \
1468 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1469 "lwz 4,8(11)\n\t" \
1470 "lwz 5,12(11)\n\t" \
1471 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1472 "lwz 7,20(11)\n\t" \
1473 "lwz 8,24(11)\n\t" \
1474 "lwz 9,28(11)\n\t" \
1475 "lwz 11,0(11)\n\t" /* target->r11 */ \
1476 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1477 "mr %0,3" \
1478 : /*out*/ "=r" (_res) \
1479 : /*in*/ "r" (&_argvec[0]) \
1480 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1481 ); \
1482 lval = (__typeof__(lval)) _res; \
1483 } while (0)
1484
1485#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1486 arg7,arg8) \
1487 do { \
1488 volatile OrigFn _orig = (orig); \
1489 volatile unsigned long _argvec[9]; \
1490 volatile unsigned long _res; \
1491 _argvec[0] = (unsigned long)_orig.nraddr; \
1492 _argvec[1] = (unsigned long)arg1; \
1493 _argvec[2] = (unsigned long)arg2; \
1494 _argvec[3] = (unsigned long)arg3; \
1495 _argvec[4] = (unsigned long)arg4; \
1496 _argvec[5] = (unsigned long)arg5; \
1497 _argvec[6] = (unsigned long)arg6; \
1498 _argvec[7] = (unsigned long)arg7; \
1499 _argvec[8] = (unsigned long)arg8; \
1500 __asm__ volatile( \
1501 "mr 11,%1\n\t" \
1502 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1503 "lwz 4,8(11)\n\t" \
1504 "lwz 5,12(11)\n\t" \
1505 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1506 "lwz 7,20(11)\n\t" \
1507 "lwz 8,24(11)\n\t" \
1508 "lwz 9,28(11)\n\t" \
1509 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
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_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1521 arg7,arg8,arg9) \
1522 do { \
1523 volatile OrigFn _orig = (orig); \
1524 volatile unsigned long _argvec[10]; \
1525 volatile unsigned long _res; \
1526 _argvec[0] = (unsigned long)_orig.nraddr; \
1527 _argvec[1] = (unsigned long)arg1; \
1528 _argvec[2] = (unsigned long)arg2; \
1529 _argvec[3] = (unsigned long)arg3; \
1530 _argvec[4] = (unsigned long)arg4; \
1531 _argvec[5] = (unsigned long)arg5; \
1532 _argvec[6] = (unsigned long)arg6; \
1533 _argvec[7] = (unsigned long)arg7; \
1534 _argvec[8] = (unsigned long)arg8; \
1535 _argvec[9] = (unsigned long)arg9; \
1536 __asm__ volatile( \
1537 "mr 11,%1\n\t" \
1538 "addi 1,1,-16\n\t" \
1539 /* arg9 */ \
1540 "lwz 3,36(11)\n\t" \
1541 "stw 3,8(1)\n\t" \
1542 /* args1-8 */ \
1543 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1544 "lwz 4,8(11)\n\t" \
1545 "lwz 5,12(11)\n\t" \
1546 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1547 "lwz 7,20(11)\n\t" \
1548 "lwz 8,24(11)\n\t" \
1549 "lwz 9,28(11)\n\t" \
1550 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1551 "lwz 11,0(11)\n\t" /* target->r11 */ \
1552 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1553 "addi 1,1,16\n\t" \
1554 "mr %0,3" \
1555 : /*out*/ "=r" (_res) \
1556 : /*in*/ "r" (&_argvec[0]) \
1557 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1558 ); \
1559 lval = (__typeof__(lval)) _res; \
1560 } while (0)
1561
1562#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1563 arg7,arg8,arg9,arg10) \
1564 do { \
1565 volatile OrigFn _orig = (orig); \
1566 volatile unsigned long _argvec[11]; \
1567 volatile unsigned long _res; \
1568 _argvec[0] = (unsigned long)_orig.nraddr; \
1569 _argvec[1] = (unsigned long)arg1; \
1570 _argvec[2] = (unsigned long)arg2; \
1571 _argvec[3] = (unsigned long)arg3; \
1572 _argvec[4] = (unsigned long)arg4; \
1573 _argvec[5] = (unsigned long)arg5; \
1574 _argvec[6] = (unsigned long)arg6; \
1575 _argvec[7] = (unsigned long)arg7; \
1576 _argvec[8] = (unsigned long)arg8; \
1577 _argvec[9] = (unsigned long)arg9; \
1578 _argvec[10] = (unsigned long)arg10; \
1579 __asm__ volatile( \
1580 "mr 11,%1\n\t" \
1581 "addi 1,1,-16\n\t" \
1582 /* arg10 */ \
1583 "lwz 3,40(11)\n\t" \
1584 "stw 3,12(1)\n\t" \
1585 /* arg9 */ \
1586 "lwz 3,36(11)\n\t" \
1587 "stw 3,8(1)\n\t" \
1588 /* args1-8 */ \
1589 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1590 "lwz 4,8(11)\n\t" \
1591 "lwz 5,12(11)\n\t" \
1592 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1593 "lwz 7,20(11)\n\t" \
1594 "lwz 8,24(11)\n\t" \
1595 "lwz 9,28(11)\n\t" \
1596 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1597 "lwz 11,0(11)\n\t" /* target->r11 */ \
1598 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1599 "addi 1,1,16\n\t" \
1600 "mr %0,3" \
1601 : /*out*/ "=r" (_res) \
1602 : /*in*/ "r" (&_argvec[0]) \
1603 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1604 ); \
1605 lval = (__typeof__(lval)) _res; \
1606 } while (0)
1607
1608#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1609 arg7,arg8,arg9,arg10,arg11) \
1610 do { \
1611 volatile OrigFn _orig = (orig); \
1612 volatile unsigned long _argvec[12]; \
1613 volatile unsigned long _res; \
1614 _argvec[0] = (unsigned long)_orig.nraddr; \
1615 _argvec[1] = (unsigned long)arg1; \
1616 _argvec[2] = (unsigned long)arg2; \
1617 _argvec[3] = (unsigned long)arg3; \
1618 _argvec[4] = (unsigned long)arg4; \
1619 _argvec[5] = (unsigned long)arg5; \
1620 _argvec[6] = (unsigned long)arg6; \
1621 _argvec[7] = (unsigned long)arg7; \
1622 _argvec[8] = (unsigned long)arg8; \
1623 _argvec[9] = (unsigned long)arg9; \
1624 _argvec[10] = (unsigned long)arg10; \
1625 _argvec[11] = (unsigned long)arg11; \
1626 __asm__ volatile( \
1627 "mr 11,%1\n\t" \
1628 "addi 1,1,-32\n\t" \
1629 /* arg11 */ \
1630 "lwz 3,44(11)\n\t" \
1631 "stw 3,16(1)\n\t" \
1632 /* arg10 */ \
1633 "lwz 3,40(11)\n\t" \
1634 "stw 3,12(1)\n\t" \
1635 /* arg9 */ \
1636 "lwz 3,36(11)\n\t" \
1637 "stw 3,8(1)\n\t" \
1638 /* args1-8 */ \
1639 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1640 "lwz 4,8(11)\n\t" \
1641 "lwz 5,12(11)\n\t" \
1642 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1643 "lwz 7,20(11)\n\t" \
1644 "lwz 8,24(11)\n\t" \
1645 "lwz 9,28(11)\n\t" \
1646 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1647 "lwz 11,0(11)\n\t" /* target->r11 */ \
1648 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1649 "addi 1,1,32\n\t" \
1650 "mr %0,3" \
1651 : /*out*/ "=r" (_res) \
1652 : /*in*/ "r" (&_argvec[0]) \
1653 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1654 ); \
1655 lval = (__typeof__(lval)) _res; \
1656 } while (0)
1657
1658#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1659 arg7,arg8,arg9,arg10,arg11,arg12) \
1660 do { \
1661 volatile OrigFn _orig = (orig); \
1662 volatile unsigned long _argvec[13]; \
1663 volatile unsigned long _res; \
1664 _argvec[0] = (unsigned long)_orig.nraddr; \
1665 _argvec[1] = (unsigned long)arg1; \
1666 _argvec[2] = (unsigned long)arg2; \
1667 _argvec[3] = (unsigned long)arg3; \
1668 _argvec[4] = (unsigned long)arg4; \
1669 _argvec[5] = (unsigned long)arg5; \
1670 _argvec[6] = (unsigned long)arg6; \
1671 _argvec[7] = (unsigned long)arg7; \
1672 _argvec[8] = (unsigned long)arg8; \
1673 _argvec[9] = (unsigned long)arg9; \
1674 _argvec[10] = (unsigned long)arg10; \
1675 _argvec[11] = (unsigned long)arg11; \
1676 _argvec[12] = (unsigned long)arg12; \
1677 __asm__ volatile( \
1678 "mr 11,%1\n\t" \
1679 "addi 1,1,-32\n\t" \
1680 /* arg12 */ \
1681 "lwz 3,48(11)\n\t" \
1682 "stw 3,20(1)\n\t" \
1683 /* arg11 */ \
1684 "lwz 3,44(11)\n\t" \
1685 "stw 3,16(1)\n\t" \
1686 /* arg10 */ \
1687 "lwz 3,40(11)\n\t" \
1688 "stw 3,12(1)\n\t" \
1689 /* arg9 */ \
1690 "lwz 3,36(11)\n\t" \
1691 "stw 3,8(1)\n\t" \
1692 /* args1-8 */ \
1693 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1694 "lwz 4,8(11)\n\t" \
1695 "lwz 5,12(11)\n\t" \
1696 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1697 "lwz 7,20(11)\n\t" \
1698 "lwz 8,24(11)\n\t" \
1699 "lwz 9,28(11)\n\t" \
1700 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1701 "lwz 11,0(11)\n\t" /* target->r11 */ \
1702 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1703 "addi 1,1,32\n\t" \
1704 "mr %0,3" \
1705 : /*out*/ "=r" (_res) \
1706 : /*in*/ "r" (&_argvec[0]) \
1707 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1708 ); \
1709 lval = (__typeof__(lval)) _res; \
1710 } while (0)
1711
sewardj0ec07f32006-01-12 12:32:32 +00001712#endif /* ARCH_ppc32 */
1713
1714/* --------------------------- ppc64 --------------------------- */
1715
sewardj9734b202006-01-17 01:49:37 +00001716#if defined(ARCH_ppc64)
1717
1718/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1719
1720/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00001721#define __CALLER_SAVED_REGS \
1722 "lr", "ctr", "xer", \
1723 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1724 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1725 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00001726
1727/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
1728 long) == 8. */
1729
sewardjd68ac3e2006-01-20 14:31:57 +00001730#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00001731 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001732 volatile OrigFn _orig = (orig); \
1733 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00001734 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001735 /* _argvec[0] holds current r2 across the call */ \
1736 _argvec[1] = (unsigned long)_orig.r2; \
1737 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00001738 __asm__ volatile( \
1739 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001740 "std 2,-16(11)\n\t" /* save tocptr */ \
1741 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1742 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00001743 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1744 "mr 11,%1\n\t" \
1745 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001746 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00001747 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00001748 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00001749 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1750 ); \
1751 lval = (__typeof__(lval)) _res; \
1752 } while (0)
1753
sewardjd68ac3e2006-01-20 14:31:57 +00001754#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00001755 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001756 volatile OrigFn _orig = (orig); \
1757 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00001758 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001759 /* _argvec[0] holds current r2 across the call */ \
1760 _argvec[1] = (unsigned long)_orig.r2; \
1761 _argvec[2] = (unsigned long)_orig.nraddr; \
1762 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00001763 __asm__ volatile( \
1764 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001765 "std 2,-16(11)\n\t" /* save tocptr */ \
1766 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1767 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1768 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00001769 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1770 "mr 11,%1\n\t" \
1771 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001772 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00001773 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00001774 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00001775 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1776 ); \
1777 lval = (__typeof__(lval)) _res; \
1778 } while (0)
1779
sewardjd68ac3e2006-01-20 14:31:57 +00001780#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00001781 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001782 volatile OrigFn _orig = (orig); \
1783 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00001784 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001785 /* _argvec[0] holds current r2 across the call */ \
1786 _argvec[1] = (unsigned long)_orig.r2; \
1787 _argvec[2] = (unsigned long)_orig.nraddr; \
1788 _argvec[2+1] = (unsigned long)arg1; \
1789 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00001790 __asm__ volatile( \
1791 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001792 "std 2,-16(11)\n\t" /* save tocptr */ \
1793 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1794 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00001795 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00001796 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00001797 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1798 "mr 11,%1\n\t" \
1799 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001800 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00001801 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00001802 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00001803 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1804 ); \
1805 lval = (__typeof__(lval)) _res; \
1806 } while (0)
1807
sewardjcd636392006-03-12 16:48:14 +00001808#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1809 do { \
1810 volatile OrigFn _orig = (orig); \
1811 volatile unsigned long _argvec[3+3]; \
1812 volatile unsigned long _res; \
1813 /* _argvec[0] holds current r2 across the call */ \
1814 _argvec[1] = (unsigned long)_orig.r2; \
1815 _argvec[2] = (unsigned long)_orig.nraddr; \
1816 _argvec[2+1] = (unsigned long)arg1; \
1817 _argvec[2+2] = (unsigned long)arg2; \
1818 _argvec[2+3] = (unsigned long)arg3; \
1819 __asm__ volatile( \
1820 "mr 11,%1\n\t" \
1821 "std 2,-16(11)\n\t" /* save tocptr */ \
1822 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1823 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1824 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1825 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1826 "ld 11, 0(11)\n\t" /* target->r11 */ \
1827 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1828 "mr 11,%1\n\t" \
1829 "mr %0,3\n\t" \
1830 "ld 2,-16(11)" /* restore tocptr */ \
1831 : /*out*/ "=r" (_res) \
1832 : /*in*/ "r" (&_argvec[2]) \
1833 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1834 ); \
1835 lval = (__typeof__(lval)) _res; \
1836 } while (0)
1837
1838#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1839 do { \
1840 volatile OrigFn _orig = (orig); \
1841 volatile unsigned long _argvec[3+4]; \
1842 volatile unsigned long _res; \
1843 /* _argvec[0] holds current r2 across the call */ \
1844 _argvec[1] = (unsigned long)_orig.r2; \
1845 _argvec[2] = (unsigned long)_orig.nraddr; \
1846 _argvec[2+1] = (unsigned long)arg1; \
1847 _argvec[2+2] = (unsigned long)arg2; \
1848 _argvec[2+3] = (unsigned long)arg3; \
1849 _argvec[2+4] = (unsigned long)arg4; \
1850 __asm__ volatile( \
1851 "mr 11,%1\n\t" \
1852 "std 2,-16(11)\n\t" /* save tocptr */ \
1853 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1854 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1855 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1856 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1857 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1858 "ld 11, 0(11)\n\t" /* target->r11 */ \
1859 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1860 "mr 11,%1\n\t" \
1861 "mr %0,3\n\t" \
1862 "ld 2,-16(11)" /* restore tocptr */ \
1863 : /*out*/ "=r" (_res) \
1864 : /*in*/ "r" (&_argvec[2]) \
1865 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1866 ); \
1867 lval = (__typeof__(lval)) _res; \
1868 } while (0)
1869
1870#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1871 do { \
1872 volatile OrigFn _orig = (orig); \
1873 volatile unsigned long _argvec[3+5]; \
1874 volatile unsigned long _res; \
1875 /* _argvec[0] holds current r2 across the call */ \
1876 _argvec[1] = (unsigned long)_orig.r2; \
1877 _argvec[2] = (unsigned long)_orig.nraddr; \
1878 _argvec[2+1] = (unsigned long)arg1; \
1879 _argvec[2+2] = (unsigned long)arg2; \
1880 _argvec[2+3] = (unsigned long)arg3; \
1881 _argvec[2+4] = (unsigned long)arg4; \
1882 _argvec[2+5] = (unsigned long)arg5; \
1883 __asm__ volatile( \
1884 "mr 11,%1\n\t" \
1885 "std 2,-16(11)\n\t" /* save tocptr */ \
1886 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1887 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1888 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1889 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1890 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1891 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1892 "ld 11, 0(11)\n\t" /* target->r11 */ \
1893 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1894 "mr 11,%1\n\t" \
1895 "mr %0,3\n\t" \
1896 "ld 2,-16(11)" /* restore tocptr */ \
1897 : /*out*/ "=r" (_res) \
1898 : /*in*/ "r" (&_argvec[2]) \
1899 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1900 ); \
1901 lval = (__typeof__(lval)) _res; \
1902 } while (0)
1903
1904#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1905 do { \
1906 volatile OrigFn _orig = (orig); \
1907 volatile unsigned long _argvec[3+6]; \
1908 volatile unsigned long _res; \
1909 /* _argvec[0] holds current r2 across the call */ \
1910 _argvec[1] = (unsigned long)_orig.r2; \
1911 _argvec[2] = (unsigned long)_orig.nraddr; \
1912 _argvec[2+1] = (unsigned long)arg1; \
1913 _argvec[2+2] = (unsigned long)arg2; \
1914 _argvec[2+3] = (unsigned long)arg3; \
1915 _argvec[2+4] = (unsigned long)arg4; \
1916 _argvec[2+5] = (unsigned long)arg5; \
1917 _argvec[2+6] = (unsigned long)arg6; \
1918 __asm__ volatile( \
1919 "mr 11,%1\n\t" \
1920 "std 2,-16(11)\n\t" /* save tocptr */ \
1921 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1922 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1923 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1924 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1925 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1926 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1927 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
1928 "ld 11, 0(11)\n\t" /* target->r11 */ \
1929 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1930 "mr 11,%1\n\t" \
1931 "mr %0,3\n\t" \
1932 "ld 2,-16(11)" /* restore tocptr */ \
1933 : /*out*/ "=r" (_res) \
1934 : /*in*/ "r" (&_argvec[2]) \
1935 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1936 ); \
1937 lval = (__typeof__(lval)) _res; \
1938 } while (0)
1939
1940#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1941 arg7) \
1942 do { \
1943 volatile OrigFn _orig = (orig); \
1944 volatile unsigned long _argvec[3+7]; \
1945 volatile unsigned long _res; \
1946 /* _argvec[0] holds current r2 across the call */ \
1947 _argvec[1] = (unsigned long)_orig.r2; \
1948 _argvec[2] = (unsigned long)_orig.nraddr; \
1949 _argvec[2+1] = (unsigned long)arg1; \
1950 _argvec[2+2] = (unsigned long)arg2; \
1951 _argvec[2+3] = (unsigned long)arg3; \
1952 _argvec[2+4] = (unsigned long)arg4; \
1953 _argvec[2+5] = (unsigned long)arg5; \
1954 _argvec[2+6] = (unsigned long)arg6; \
1955 _argvec[2+7] = (unsigned long)arg7; \
1956 __asm__ volatile( \
1957 "mr 11,%1\n\t" \
1958 "std 2,-16(11)\n\t" /* save tocptr */ \
1959 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1960 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1961 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1962 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1963 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1964 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1965 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
1966 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
1967 "ld 11, 0(11)\n\t" /* target->r11 */ \
1968 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1969 "mr 11,%1\n\t" \
1970 "mr %0,3\n\t" \
1971 "ld 2,-16(11)" /* restore tocptr */ \
1972 : /*out*/ "=r" (_res) \
1973 : /*in*/ "r" (&_argvec[2]) \
1974 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1975 ); \
1976 lval = (__typeof__(lval)) _res; \
1977 } while (0)
1978
1979#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1980 arg7,arg8) \
1981 do { \
1982 volatile OrigFn _orig = (orig); \
1983 volatile unsigned long _argvec[3+8]; \
1984 volatile unsigned long _res; \
1985 /* _argvec[0] holds current r2 across the call */ \
1986 _argvec[1] = (unsigned long)_orig.r2; \
1987 _argvec[2] = (unsigned long)_orig.nraddr; \
1988 _argvec[2+1] = (unsigned long)arg1; \
1989 _argvec[2+2] = (unsigned long)arg2; \
1990 _argvec[2+3] = (unsigned long)arg3; \
1991 _argvec[2+4] = (unsigned long)arg4; \
1992 _argvec[2+5] = (unsigned long)arg5; \
1993 _argvec[2+6] = (unsigned long)arg6; \
1994 _argvec[2+7] = (unsigned long)arg7; \
1995 _argvec[2+8] = (unsigned long)arg8; \
1996 __asm__ volatile( \
1997 "mr 11,%1\n\t" \
1998 "std 2,-16(11)\n\t" /* save tocptr */ \
1999 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2000 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2001 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2002 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2003 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2004 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2005 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2006 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2007 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2008 "ld 11, 0(11)\n\t" /* target->r11 */ \
2009 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2010 "mr 11,%1\n\t" \
2011 "mr %0,3\n\t" \
2012 "ld 2,-16(11)" /* restore tocptr */ \
2013 : /*out*/ "=r" (_res) \
2014 : /*in*/ "r" (&_argvec[2]) \
2015 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2016 ); \
2017 lval = (__typeof__(lval)) _res; \
2018 } while (0)
2019
2020#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2021 arg7,arg8,arg9) \
2022 do { \
2023 volatile OrigFn _orig = (orig); \
2024 volatile unsigned long _argvec[3+9]; \
2025 volatile unsigned long _res; \
2026 /* _argvec[0] holds current r2 across the call */ \
2027 _argvec[1] = (unsigned long)_orig.r2; \
2028 _argvec[2] = (unsigned long)_orig.nraddr; \
2029 _argvec[2+1] = (unsigned long)arg1; \
2030 _argvec[2+2] = (unsigned long)arg2; \
2031 _argvec[2+3] = (unsigned long)arg3; \
2032 _argvec[2+4] = (unsigned long)arg4; \
2033 _argvec[2+5] = (unsigned long)arg5; \
2034 _argvec[2+6] = (unsigned long)arg6; \
2035 _argvec[2+7] = (unsigned long)arg7; \
2036 _argvec[2+8] = (unsigned long)arg8; \
2037 _argvec[2+9] = (unsigned long)arg9; \
2038 __asm__ volatile( \
2039 "mr 11,%1\n\t" \
2040 "std 2,-16(11)\n\t" /* save tocptr */ \
2041 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2042 "addi 1,1,-128\n\t" /* expand stack frame */ \
2043 /* arg9 */ \
2044 "ld 3,72(11)\n\t" \
2045 "std 3,112(1)\n\t" \
2046 /* args1-8 */ \
2047 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2048 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2049 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2050 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2051 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2052 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2053 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2054 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2055 "ld 11, 0(11)\n\t" /* target->r11 */ \
2056 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2057 "mr 11,%1\n\t" \
2058 "mr %0,3\n\t" \
2059 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2060 "addi 1,1,128" /* restore frame */ \
2061 : /*out*/ "=r" (_res) \
2062 : /*in*/ "r" (&_argvec[2]) \
2063 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2064 ); \
2065 lval = (__typeof__(lval)) _res; \
2066 } while (0)
2067
2068#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2069 arg7,arg8,arg9,arg10) \
2070 do { \
2071 volatile OrigFn _orig = (orig); \
2072 volatile unsigned long _argvec[3+10]; \
2073 volatile unsigned long _res; \
2074 /* _argvec[0] holds current r2 across the call */ \
2075 _argvec[1] = (unsigned long)_orig.r2; \
2076 _argvec[2] = (unsigned long)_orig.nraddr; \
2077 _argvec[2+1] = (unsigned long)arg1; \
2078 _argvec[2+2] = (unsigned long)arg2; \
2079 _argvec[2+3] = (unsigned long)arg3; \
2080 _argvec[2+4] = (unsigned long)arg4; \
2081 _argvec[2+5] = (unsigned long)arg5; \
2082 _argvec[2+6] = (unsigned long)arg6; \
2083 _argvec[2+7] = (unsigned long)arg7; \
2084 _argvec[2+8] = (unsigned long)arg8; \
2085 _argvec[2+9] = (unsigned long)arg9; \
2086 _argvec[2+10] = (unsigned long)arg10; \
2087 __asm__ volatile( \
2088 "mr 11,%1\n\t" \
2089 "std 2,-16(11)\n\t" /* save tocptr */ \
2090 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2091 "addi 1,1,-128\n\t" /* expand stack frame */ \
2092 /* arg10 */ \
2093 "ld 3,80(11)\n\t" \
2094 "std 3,120(1)\n\t" \
2095 /* arg9 */ \
2096 "ld 3,72(11)\n\t" \
2097 "std 3,112(1)\n\t" \
2098 /* args1-8 */ \
2099 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2100 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2101 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2102 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2103 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2104 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2105 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2106 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2107 "ld 11, 0(11)\n\t" /* target->r11 */ \
2108 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2109 "mr 11,%1\n\t" \
2110 "mr %0,3\n\t" \
2111 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2112 "addi 1,1,128" /* restore frame */ \
2113 : /*out*/ "=r" (_res) \
2114 : /*in*/ "r" (&_argvec[2]) \
2115 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2116 ); \
2117 lval = (__typeof__(lval)) _res; \
2118 } while (0)
2119
2120#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2121 arg7,arg8,arg9,arg10,arg11) \
2122 do { \
2123 volatile OrigFn _orig = (orig); \
2124 volatile unsigned long _argvec[3+11]; \
2125 volatile unsigned long _res; \
2126 /* _argvec[0] holds current r2 across the call */ \
2127 _argvec[1] = (unsigned long)_orig.r2; \
2128 _argvec[2] = (unsigned long)_orig.nraddr; \
2129 _argvec[2+1] = (unsigned long)arg1; \
2130 _argvec[2+2] = (unsigned long)arg2; \
2131 _argvec[2+3] = (unsigned long)arg3; \
2132 _argvec[2+4] = (unsigned long)arg4; \
2133 _argvec[2+5] = (unsigned long)arg5; \
2134 _argvec[2+6] = (unsigned long)arg6; \
2135 _argvec[2+7] = (unsigned long)arg7; \
2136 _argvec[2+8] = (unsigned long)arg8; \
2137 _argvec[2+9] = (unsigned long)arg9; \
2138 _argvec[2+10] = (unsigned long)arg10; \
2139 _argvec[2+11] = (unsigned long)arg11; \
2140 __asm__ volatile( \
2141 "mr 11,%1\n\t" \
2142 "std 2,-16(11)\n\t" /* save tocptr */ \
2143 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2144 "addi 1,1,-144\n\t" /* expand stack frame */ \
2145 /* arg11 */ \
2146 "ld 3,88(11)\n\t" \
2147 "std 3,128(1)\n\t" \
2148 /* arg10 */ \
2149 "ld 3,80(11)\n\t" \
2150 "std 3,120(1)\n\t" \
2151 /* arg9 */ \
2152 "ld 3,72(11)\n\t" \
2153 "std 3,112(1)\n\t" \
2154 /* args1-8 */ \
2155 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2156 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2157 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2158 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2159 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2160 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2161 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2162 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2163 "ld 11, 0(11)\n\t" /* target->r11 */ \
2164 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2165 "mr 11,%1\n\t" \
2166 "mr %0,3\n\t" \
2167 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2168 "addi 1,1,144" /* restore frame */ \
2169 : /*out*/ "=r" (_res) \
2170 : /*in*/ "r" (&_argvec[2]) \
2171 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2172 ); \
2173 lval = (__typeof__(lval)) _res; \
2174 } while (0)
2175
2176#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2177 arg7,arg8,arg9,arg10,arg11,arg12) \
2178 do { \
2179 volatile OrigFn _orig = (orig); \
2180 volatile unsigned long _argvec[3+12]; \
2181 volatile unsigned long _res; \
2182 /* _argvec[0] holds current r2 across the call */ \
2183 _argvec[1] = (unsigned long)_orig.r2; \
2184 _argvec[2] = (unsigned long)_orig.nraddr; \
2185 _argvec[2+1] = (unsigned long)arg1; \
2186 _argvec[2+2] = (unsigned long)arg2; \
2187 _argvec[2+3] = (unsigned long)arg3; \
2188 _argvec[2+4] = (unsigned long)arg4; \
2189 _argvec[2+5] = (unsigned long)arg5; \
2190 _argvec[2+6] = (unsigned long)arg6; \
2191 _argvec[2+7] = (unsigned long)arg7; \
2192 _argvec[2+8] = (unsigned long)arg8; \
2193 _argvec[2+9] = (unsigned long)arg9; \
2194 _argvec[2+10] = (unsigned long)arg10; \
2195 _argvec[2+11] = (unsigned long)arg11; \
2196 _argvec[2+12] = (unsigned long)arg12; \
2197 __asm__ volatile( \
2198 "mr 11,%1\n\t" \
2199 "std 2,-16(11)\n\t" /* save tocptr */ \
2200 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2201 "addi 1,1,-144\n\t" /* expand stack frame */ \
2202 /* arg12 */ \
2203 "ld 3,96(11)\n\t" \
2204 "std 3,136(1)\n\t" \
2205 /* arg11 */ \
2206 "ld 3,88(11)\n\t" \
2207 "std 3,128(1)\n\t" \
2208 /* arg10 */ \
2209 "ld 3,80(11)\n\t" \
2210 "std 3,120(1)\n\t" \
2211 /* arg9 */ \
2212 "ld 3,72(11)\n\t" \
2213 "std 3,112(1)\n\t" \
2214 /* args1-8 */ \
2215 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2216 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2217 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2218 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2219 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2220 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2221 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2222 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2223 "ld 11, 0(11)\n\t" /* target->r11 */ \
2224 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2225 "mr 11,%1\n\t" \
2226 "mr %0,3\n\t" \
2227 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2228 "addi 1,1,144" /* restore frame */ \
2229 : /*out*/ "=r" (_res) \
2230 : /*in*/ "r" (&_argvec[2]) \
2231 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2232 ); \
2233 lval = (__typeof__(lval)) _res; \
2234 } while (0)
2235
sewardj9734b202006-01-17 01:49:37 +00002236#endif /* ARCH_ppc64 */
2237
sewardj0ec07f32006-01-12 12:32:32 +00002238
2239/* ------------------------------------------------------------------ */
2240/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
2241/* */
njn30d76c62005-06-18 15:07:39 +00002242/* ------------------------------------------------------------------ */
2243
sewardj2e93c502002-04-12 11:12:52 +00002244/* Some request codes. There are many more of these, but most are not
2245 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00002246 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00002247
sewardj0ec07f32006-01-12 12:32:32 +00002248 Core ones are in the range 0x00000000--0x0000ffff. The non-public
2249 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00002250*/
2251
sewardj0ec07f32006-01-12 12:32:32 +00002252/* These macros are used by tools -- they must be public, but don't
2253 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00002254#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00002255 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00002256#define VG_IS_TOOL_USERREQ(a, b, v) \
2257 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00002258
sewardj5ce4b152006-03-11 12:57:41 +00002259/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
2260 This enum comprises an ABI exported by Valgrind to programs
2261 which use client requests. DO NOT CHANGE THE ORDER OF THESE
2262 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00002263typedef
njn4c791212003-05-02 17:53:54 +00002264 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
2265 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00002266
sewardj0ec07f32006-01-12 12:32:32 +00002267 /* These allow any function to be called from the simulated
2268 CPU but run on the real CPU. Nb: the first arg passed to
2269 the function is always the ThreadId of the running
2270 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00002271 function, etc. */
njn4c791212003-05-02 17:53:54 +00002272 VG_USERREQ__CLIENT_CALL0 = 0x1101,
2273 VG_USERREQ__CLIENT_CALL1 = 0x1102,
2274 VG_USERREQ__CLIENT_CALL2 = 0x1103,
2275 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00002276
sewardj0ec07f32006-01-12 12:32:32 +00002277 /* Can be useful in regression testing suites -- eg. can
2278 send Valgrind's output to /dev/null and still count
2279 errors. */
njn4c791212003-05-02 17:53:54 +00002280 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00002281
sewardj0ec07f32006-01-12 12:32:32 +00002282 /* These are useful and can be interpreted by any tool that
2283 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00002284 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
2285 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00002286 /* Memory pool support. */
2287 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
2288 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
2289 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
2290 VG_USERREQ__MEMPOOL_FREE = 0x1306,
njnd7994182003-10-02 13:44:04 +00002291
fitzhardinge39de4b42003-10-31 07:12:21 +00002292 /* Allow printfs to valgrind log. */
njn30d76c62005-06-18 15:07:39 +00002293 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00002294 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
2295
2296 /* Stack support. */
2297 VG_USERREQ__STACK_REGISTER = 0x1501,
2298 VG_USERREQ__STACK_DEREGISTER = 0x1502,
2299 VG_USERREQ__STACK_CHANGE = 0x1503,
njn25e49d8e72002-09-23 09:36:25 +00002300 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00002301
sewardj0ec07f32006-01-12 12:32:32 +00002302#if !defined(__GNUC__)
2303# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00002304#endif
sewardj2e93c502002-04-12 11:12:52 +00002305
sewardj0ec07f32006-01-12 12:32:32 +00002306/* Returns the number of Valgrinds this code is running under. That
2307 is, 0 if running natively, 1 if running under Valgrind, 2 if
2308 running under Valgrind which is running under another Valgrind,
2309 etc. */
2310#define RUNNING_ON_VALGRIND __extension__ \
2311 ({unsigned int _qzz_res; \
2312 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \
2313 VG_USERREQ__RUNNING_ON_VALGRIND, \
sewardj9af10a12006-02-01 14:59:42 +00002314 0, 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00002315 _qzz_res; \
sewardjde4a1d02002-03-22 01:27:54 +00002316 })
2317
2318
sewardj18d75132002-05-16 11:06:21 +00002319/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
2320 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
2321 since it provides a way to make sure valgrind will retranslate the
2322 invalidated area. Returns no value. */
sewardj0ec07f32006-01-12 12:32:32 +00002323#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
2324 {unsigned int _qzz_res; \
2325 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2326 VG_USERREQ__DISCARD_TRANSLATIONS, \
sewardj9af10a12006-02-01 14:59:42 +00002327 _qzz_addr, _qzz_len, 0, 0, 0); \
sewardj18d75132002-05-16 11:06:21 +00002328 }
2329
njn26aba4d2005-05-16 13:31:23 +00002330
sewardj0ec07f32006-01-12 12:32:32 +00002331/* These requests are for getting Valgrind itself to print something.
2332 Possibly with a backtrace. This is a really ugly hack. */
2333
2334#if defined(NVALGRIND)
2335
2336# define VALGRIND_PRINTF(...)
2337# define VALGRIND_PRINTF_BACKTRACE(...)
njn26aba4d2005-05-16 13:31:23 +00002338
2339#else /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00002340
sewardj7eca0cc2006-04-12 17:15:35 +00002341/* Modern GCC will optimize the static routine out if unused,
2342 and unused attribute will shut down warnings about it. */
2343static int VALGRIND_PRINTF(const char *format, ...)
2344 __attribute__((format(__printf__, 1, 2), __unused__));
2345static int
fitzhardingea09a1b52003-11-07 23:09:48 +00002346VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00002347{
njnc6168192004-11-29 13:54:10 +00002348 unsigned long _qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00002349 va_list vargs;
2350 va_start(vargs, format);
sewardj0ec07f32006-01-12 12:32:32 +00002351 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF,
sewardj9af10a12006-02-01 14:59:42 +00002352 (unsigned long)format, (unsigned long)vargs,
2353 0, 0, 0);
fitzhardinge39de4b42003-10-31 07:12:21 +00002354 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00002355 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00002356}
2357
sewardj7eca0cc2006-04-12 17:15:35 +00002358static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
2359 __attribute__((format(__printf__, 1, 2), __unused__));
2360static int
fitzhardingea09a1b52003-11-07 23:09:48 +00002361VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00002362{
njnc6168192004-11-29 13:54:10 +00002363 unsigned long _qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00002364 va_list vargs;
2365 va_start(vargs, format);
sewardj0ec07f32006-01-12 12:32:32 +00002366 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE,
sewardj9af10a12006-02-01 14:59:42 +00002367 (unsigned long)format, (unsigned long)vargs,
2368 0, 0, 0);
fitzhardinge39de4b42003-10-31 07:12:21 +00002369 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00002370 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00002371}
2372
fitzhardinge39de4b42003-10-31 07:12:21 +00002373#endif /* NVALGRIND */
sewardj18d75132002-05-16 11:06:21 +00002374
sewardj0ec07f32006-01-12 12:32:32 +00002375
njn3e884182003-04-15 13:03:23 +00002376/* These requests allow control to move from the simulated CPU to the
2377 real CPU, calling an arbitary function */
sewardj0ec07f32006-01-12 12:32:32 +00002378#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
2379 ({unsigned long _qyy_res; \
2380 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
2381 VG_USERREQ__CLIENT_CALL0, \
2382 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00002383 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00002384 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00002385 })
2386
sewardj0ec07f32006-01-12 12:32:32 +00002387#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
2388 ({unsigned long _qyy_res; \
2389 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
2390 VG_USERREQ__CLIENT_CALL1, \
2391 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00002392 _qyy_arg1, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00002393 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00002394 })
2395
sewardj0ec07f32006-01-12 12:32:32 +00002396#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
2397 ({unsigned long _qyy_res; \
2398 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
2399 VG_USERREQ__CLIENT_CALL2, \
2400 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00002401 _qyy_arg1, _qyy_arg2, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00002402 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00002403 })
2404
sewardj0ec07f32006-01-12 12:32:32 +00002405#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
2406 ({unsigned long _qyy_res; \
2407 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
2408 VG_USERREQ__CLIENT_CALL3, \
2409 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00002410 _qyy_arg1, _qyy_arg2, \
2411 _qyy_arg3, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00002412 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00002413 })
2414
2415
nethercote7cc9c232004-01-21 15:08:04 +00002416/* Counts the number of errors that have been recorded by a tool. Nb:
2417 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00002418 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00002419#define VALGRIND_COUNT_ERRORS \
2420 ({unsigned int _qyy_res; \
2421 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
2422 VG_USERREQ__COUNT_ERRORS, \
sewardj9af10a12006-02-01 14:59:42 +00002423 0, 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00002424 _qyy_res; \
njn47363ab2003-04-21 13:24:40 +00002425 })
2426
njnd7994182003-10-02 13:44:04 +00002427/* Mark a block of memory as having been allocated by a malloc()-like
2428 function. `addr' is the start of the usable block (ie. after any
2429 redzone) `rzB' is redzone size if the allocator can apply redzones;
2430 use '0' if not. Adding redzones makes it more likely Valgrind will spot
2431 block overruns. `is_zeroed' indicates if the memory is zeroed, as it is
2432 for calloc(). Put it immediately after the point where a block is
2433 allocated.
2434
2435 If you're allocating memory via superblocks, and then handing out small
2436 chunks of each superblock, if you don't have redzones on your small
njndbf7ca72006-03-31 11:57:59 +00002437 blocks, it's worth marking the superblock with VALGRIND_MAKE_MEM_NOACCESS
njnd7994182003-10-02 13:44:04 +00002438 when it's created, so that block overruns are detected. But if you can
2439 put redzones on, it's probably better to not do this, so that messages
2440 for small overruns are described in terms of the small block rather than
2441 the superblock (but if you have a big overrun that skips over a redzone,
2442 you could miss an error this way). See memcheck/tests/custom_alloc.c
2443 for an example.
2444
2445 Nb: block must be freed via a free()-like function specified
2446 with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */
sewardj0ec07f32006-01-12 12:32:32 +00002447#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
2448 {unsigned int _qzz_res; \
2449 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2450 VG_USERREQ__MALLOCLIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00002451 addr, sizeB, rzB, is_zeroed, 0); \
njnd7994182003-10-02 13:44:04 +00002452 }
2453
2454/* Mark a block of memory as having been freed by a free()-like function.
2455 `rzB' is redzone size; it must match that given to
2456 VALGRIND_MALLOCLIKE_BLOCK. Memory not freed will be detected by the leak
2457 checker. Put it immediately after the point where the block is freed. */
sewardj0ec07f32006-01-12 12:32:32 +00002458#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
2459 {unsigned int _qzz_res; \
2460 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2461 VG_USERREQ__FREELIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00002462 addr, rzB, 0, 0, 0); \
njnd7994182003-10-02 13:44:04 +00002463 }
2464
rjwalshbc0bb832004-06-19 18:12:36 +00002465/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00002466#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
2467 {unsigned int _qzz_res; \
2468 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2469 VG_USERREQ__CREATE_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00002470 pool, rzB, is_zeroed, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00002471 }
2472
2473/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00002474#define VALGRIND_DESTROY_MEMPOOL(pool) \
2475 {unsigned int _qzz_res; \
2476 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2477 VG_USERREQ__DESTROY_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00002478 pool, 0, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00002479 }
2480
2481/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00002482#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
2483 {unsigned int _qzz_res; \
2484 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2485 VG_USERREQ__MEMPOOL_ALLOC, \
sewardj9af10a12006-02-01 14:59:42 +00002486 pool, addr, size, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00002487 }
2488
2489/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00002490#define VALGRIND_MEMPOOL_FREE(pool, addr) \
2491 {unsigned int _qzz_res; \
2492 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2493 VG_USERREQ__MEMPOOL_FREE, \
sewardj9af10a12006-02-01 14:59:42 +00002494 pool, addr, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00002495 }
2496
rjwalsh0140af52005-06-04 20:42:33 +00002497/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00002498#define VALGRIND_STACK_REGISTER(start, end) \
2499 ({unsigned int _qzz_res; \
2500 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2501 VG_USERREQ__STACK_REGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00002502 start, end, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00002503 _qzz_res; \
rjwalsh0140af52005-06-04 20:42:33 +00002504 })
2505
2506/* Unmark the piece of memory associated with a stack id as being a
2507 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00002508#define VALGRIND_STACK_DEREGISTER(id) \
2509 {unsigned int _qzz_res; \
2510 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2511 VG_USERREQ__STACK_DEREGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00002512 id, 0, 0, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00002513 }
2514
2515/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00002516#define VALGRIND_STACK_CHANGE(id, start, end) \
2517 {unsigned int _qzz_res; \
2518 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2519 VG_USERREQ__STACK_CHANGE, \
sewardj9af10a12006-02-01 14:59:42 +00002520 id, start, end, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00002521 }
2522
sewardj0ec07f32006-01-12 12:32:32 +00002523
2524#undef ARCH_x86
2525#undef ARCH_amd64
2526#undef ARCH_ppc32
2527#undef ARCH_ppc64
2528
njn3e884182003-04-15 13:03:23 +00002529#endif /* __VALGRIND_H */