blob: e92c58a1c9f163e6dcdfbf99f0c8a785ce18f3fe [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
5 file (valgrind.h) only. The entire rest of Valgrind is licensed
6 under the terms of the GNU General Public License, version 2. See
7 the COPYING file in the source distribution for details.
8
9 ----------------------------------------------------------------
10
njnb9c427c2004-12-01 14:14:42 +000011 This file is part of Valgrind, a dynamic binary instrumentation
12 framework.
sewardjde4a1d02002-03-22 01:27:54 +000013
njn53612422005-03-12 16:22:54 +000014 Copyright (C) 2000-2005 Julian Seward. All rights reserved.
sewardjde4a1d02002-03-22 01:27:54 +000015
njn25e49d8e72002-09-23 09:36:25 +000016 Redistribution and use in source and binary forms, with or without
17 modification, are permitted provided that the following conditions
18 are met:
sewardjde4a1d02002-03-22 01:27:54 +000019
njn25e49d8e72002-09-23 09:36:25 +000020 1. Redistributions of source code must retain the above copyright
21 notice, this list of conditions and the following disclaimer.
sewardjde4a1d02002-03-22 01:27:54 +000022
njn25e49d8e72002-09-23 09:36:25 +000023 2. The origin of this software must not be misrepresented; you must
24 not claim that you wrote the original software. If you use this
25 software in a product, an acknowledgment in the product
26 documentation would be appreciated but is not required.
sewardjde4a1d02002-03-22 01:27:54 +000027
njn25e49d8e72002-09-23 09:36:25 +000028 3. Altered source versions must be plainly marked as such, and must
29 not be misrepresented as being the original software.
30
31 4. The name of the author may not be used to endorse or promote
32 products derived from this software without specific prior written
33 permission.
34
35 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
36 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
37 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
39 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
42 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
43 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
44 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
45 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46
47 ----------------------------------------------------------------
48
49 Notice that the above BSD-style license applies to this one file
50 (valgrind.h) only. The entire rest of Valgrind is licensed under
51 the terms of the GNU General Public License, version 2. See the
52 COPYING file in the source distribution for details.
53
54 ----------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +000055*/
56
57
njn30d76c62005-06-18 15:07:39 +000058/* This file is for inclusion into client (your!) code.
59
60 You can use these macros to manipulate and query Valgrind's
61 execution inside your own programs.
62
63 The resulting executables will still run without Valgrind, just a
64 little bit more slowly than they otherwise would, but otherwise
65 unchanged. When not running on valgrind, each client request
sewardj0ec07f32006-01-12 12:32:32 +000066 consumes very few (eg. 7) instructions, so the resulting performance
njn30d76c62005-06-18 15:07:39 +000067 loss is negligible unless you plan to execute client requests
68 millions of times per second. Nevertheless, if that is still a
69 problem, you can compile with the NVALGRIND symbol defined (gcc
70 -DNVALGRIND) so that client requests are not even compiled in. */
71
sewardjde4a1d02002-03-22 01:27:54 +000072#ifndef __VALGRIND_H
73#define __VALGRIND_H
74
fitzhardinge39de4b42003-10-31 07:12:21 +000075#include <stdarg.h>
76
njn3dd0a912005-06-28 19:44:10 +000077/* Nb: this file might be included in a file compiled with -ansi. So
78 we can't use C++ style "//" comments nor the "asm" keyword (instead
79 use "__asm__"). */
80
sewardj0ec07f32006-01-12 12:32:32 +000081/* Derive some tags indicating what the target architecture is. Note
82 that in this file we're using the compiler's CPP symbols for
83 identifying architectures, which are different to the ones we use
84 within the rest of Valgrind. Note, __powerpc__ is active for both
85 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
86 latter. */
87#undef ARCH_x86
88#undef ARCH_amd64
89#undef ARCH_ppc32
90#undef ARCH_ppc64
91
92#if defined(__i386__)
93# define ARCH_x86 1
94#elif defined(__x86_64__)
95# define ARCH_amd64 1
96#elif defined(__powerpc__) && !defined(__powerpc64__)
97# define ARCH_ppc32 1
98#elif defined(__powerpc__) && defined(__powerpc64__)
99# define ARCH_ppc64 1
sewardjb5f6f512005-03-10 23:59:00 +0000100#endif
101
sewardj0ec07f32006-01-12 12:32:32 +0000102/* If we're not compiling for our target architecture, don't generate
103 any inline asms. */
104#if !defined(ARCH_x86) && !defined(ARCH_amd64) \
105 && !defined(ARCH_ppc32) && !defined(ARCH_ppc64)
106# if !defined(NVALGRIND)
107# define NVALGRIND 1
108# endif
109#endif
110
111
njn30d76c62005-06-18 15:07:39 +0000112/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000113/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
114/* in here of use to end-users -- skip to the next section. */
njn30d76c62005-06-18 15:07:39 +0000115/* ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000116
sewardj0ec07f32006-01-12 12:32:32 +0000117#if defined(NVALGRIND)
njn26aba4d2005-05-16 13:31:23 +0000118
119/* Define NVALGRIND to completely remove the Valgrind magic sequence
sewardj0ec07f32006-01-12 12:32:32 +0000120 from the compiled code (analogous to NDEBUG's effects on
121 assert()) */
122#define VALGRIND_DO_CLIENT_REQUEST( \
123 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000124 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000125 { \
126 (_zzq_rlval) = (_zzq_default); \
njn26aba4d2005-05-16 13:31:23 +0000127 }
128
sewardj0ec07f32006-01-12 12:32:32 +0000129#else /* ! NVALGRIND */
nethercotee90c6832004-10-18 18:07:49 +0000130
sewardj0ec07f32006-01-12 12:32:32 +0000131/* The following defines the magic code sequences which the JITter
132 spots and handles magically. Don't look too closely at them as
133 they will rot your brain.
134
135 The assembly code sequences for all architectures is in this one
136 file. This is because this file must be stand-alone, and we don't
137 want to have multiple files.
138
139 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
140 value gets put in the return slot, so that everything works when
141 this is executed not under Valgrind. Args are passed in a memory
142 block, and so there's no intrinsic limit to the number that could
sewardj9af10a12006-02-01 14:59:42 +0000143 be passed, but it's currently five.
nethercotee90c6832004-10-18 18:07:49 +0000144
nethercote54265442004-10-26 12:56:58 +0000145 The macro args are:
146 _zzq_rlval result lvalue
147 _zzq_default default value (result returned when running on real CPU)
148 _zzq_request request code
sewardj9af10a12006-02-01 14:59:42 +0000149 _zzq_arg1..5 request params
nethercote54265442004-10-26 12:56:58 +0000150
sewardj0ec07f32006-01-12 12:32:32 +0000151 The other two macros are used to support function wrapping, and are
sewardjd68ac3e2006-01-20 14:31:57 +0000152 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
153 guest's NRADDR pseudo-register and whatever other information is
154 needed to safely run the call original from the wrapper: on
155 ppc64-linux, the R2 value at the divert point is also needed. This
156 information is abstracted into a user-visible type, OrigFn.
157
158 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
159 guest, but guarantees that the branch instruction will not be
160 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
161 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
162 complete inline asm, since it needs to be combined with more magic
163 inline asm stuff to be useful.
nethercotee90c6832004-10-18 18:07:49 +0000164*/
165
sewardj0ec07f32006-01-12 12:32:32 +0000166/* ---------------------------- x86 ---------------------------- */
sewardjde4a4ab2005-03-23 13:10:32 +0000167
sewardj0ec07f32006-01-12 12:32:32 +0000168#if defined(ARCH_x86)
sewardjc8858442006-01-20 15:17:20 +0000169
170typedef
171 struct {
172 unsigned int nraddr; /* where's the code? */
173 }
174 OrigFn;
175
sewardj0ec07f32006-01-12 12:32:32 +0000176#define __SPECIAL_INSTRUCTION_PREAMBLE \
177 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000178 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000179
sewardj0ec07f32006-01-12 12:32:32 +0000180#define VALGRIND_DO_CLIENT_REQUEST( \
181 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000182 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
183 { volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000184 volatile unsigned int _zzq_result; \
185 _zzq_args[0] = (unsigned int)(_zzq_request); \
186 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
187 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
188 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
189 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000190 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000191 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
192 /* %EDX = client_request ( %EAX ) */ \
193 "xchgl %%ebx,%%ebx" \
194 : "=d" (_zzq_result) \
195 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
196 : "cc", "memory" \
197 ); \
198 _zzq_rlval = _zzq_result; \
cerion85665ca2005-06-20 15:51:07 +0000199 }
sewardj2c48c7b2005-11-29 13:05:56 +0000200
sewardjc8858442006-01-20 15:17:20 +0000201#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
202 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
203 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000204 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
205 /* %EAX = guest_NRADDR */ \
206 "xchgl %%ecx,%%ecx" \
207 : "=a" (__addr) \
208 : \
209 : "cc", "memory" \
210 ); \
sewardjc8858442006-01-20 15:17:20 +0000211 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000212 }
sewardj0ec07f32006-01-12 12:32:32 +0000213
214#define VALGRIND_CALL_NOREDIR_EAX \
215 __SPECIAL_INSTRUCTION_PREAMBLE \
216 /* call-noredir *%EAX */ \
217 "xchgl %%edx,%%edx\n\t"
218#endif /* ARCH_x86 */
219
220/* --------------------------- amd64 --------------------------- */
221
222#if defined(ARCH_amd64)
sewardjc8858442006-01-20 15:17:20 +0000223
224typedef
225 struct {
226 unsigned long long int nraddr; /* where's the code? */
227 }
228 OrigFn;
229
sewardj0ec07f32006-01-12 12:32:32 +0000230#define __SPECIAL_INSTRUCTION_PREAMBLE \
231 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000232 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000233
234#define VALGRIND_DO_CLIENT_REQUEST( \
235 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000236 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
237 { volatile unsigned long long int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000238 volatile unsigned long long int _zzq_result; \
239 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
240 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
241 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
242 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
243 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000244 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000245 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
246 /* %RDX = client_request ( %RAX ) */ \
247 "xchgq %%rbx,%%rbx" \
248 : "=d" (_zzq_result) \
249 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
250 : "cc", "memory" \
251 ); \
252 _zzq_rlval = _zzq_result; \
253 }
254
sewardjc8858442006-01-20 15:17:20 +0000255#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
256 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
257 volatile unsigned long long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000258 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
259 /* %RAX = guest_NRADDR */ \
260 "xchgq %%rcx,%%rcx" \
261 : "=a" (__addr) \
262 : \
263 : "cc", "memory" \
264 ); \
sewardjc8858442006-01-20 15:17:20 +0000265 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000266 }
267
268#define VALGRIND_CALL_NOREDIR_RAX \
269 __SPECIAL_INSTRUCTION_PREAMBLE \
270 /* call-noredir *%RAX */ \
271 "xchgq %%rdx,%%rdx\n\t"
272#endif /* ARCH_amd64 */
273
274/* --------------------------- ppc32 --------------------------- */
275
276#if defined(ARCH_ppc32)
sewardjd68ac3e2006-01-20 14:31:57 +0000277
278typedef
279 struct {
sewardjc8858442006-01-20 15:17:20 +0000280 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000281 }
282 OrigFn;
283
sewardj0ec07f32006-01-12 12:32:32 +0000284#define __SPECIAL_INSTRUCTION_PREAMBLE \
285 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000286 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000287
288#define VALGRIND_DO_CLIENT_REQUEST( \
289 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000290 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000291 \
sewardj9af10a12006-02-01 14:59:42 +0000292 { unsigned int _zzq_args[6]; \
sewardj1a85f4f2006-01-12 21:15:35 +0000293 register unsigned int _zzq_result __asm__("r3"); \
294 register unsigned int* _zzq_ptr __asm__("r4"); \
sewardj0ec07f32006-01-12 12:32:32 +0000295 _zzq_args[0] = (unsigned int)(_zzq_request); \
296 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
297 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
298 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
299 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000300 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000301 _zzq_ptr = _zzq_args; \
302 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
303 /* %R3 = client_request ( %R4 ) */ \
304 "or 1,1,1" \
305 : "=r" (_zzq_result) \
306 : "0" (_zzq_default), "r" (_zzq_ptr) \
307 : "cc", "memory"); \
308 _zzq_rlval = _zzq_result; \
309 }
310
sewardjd68ac3e2006-01-20 14:31:57 +0000311#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
312 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
313 register unsigned int __addr __asm__("r3"); \
sewardj0ec07f32006-01-12 12:32:32 +0000314 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
315 /* %R3 = guest_NRADDR */ \
316 "or 2,2,2" \
317 : "=r" (__addr) \
318 : \
319 : "cc", "memory" \
320 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000321 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000322 }
323
324#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
325 __SPECIAL_INSTRUCTION_PREAMBLE \
326 /* branch-and-link-to-noredir *%R11 */ \
327 "or 3,3,3\n\t"
328#endif /* ARCH_ppc32 */
329
330/* --------------------------- ppc64 --------------------------- */
331
332#if defined(ARCH_ppc64)
sewardjd68ac3e2006-01-20 14:31:57 +0000333
334typedef
335 struct {
336 unsigned long long int nraddr; /* where's the code? */
337 unsigned long long int r2; /* what tocptr do we need? */
338 }
339 OrigFn;
340
sewardj1a85f4f2006-01-12 21:15:35 +0000341#define __SPECIAL_INSTRUCTION_PREAMBLE \
342 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
343 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
344
sewardj0ec07f32006-01-12 12:32:32 +0000345#define VALGRIND_DO_CLIENT_REQUEST( \
346 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000347 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000348 \
sewardj9af10a12006-02-01 14:59:42 +0000349 { unsigned long long int _zzq_args[6]; \
sewardj1a85f4f2006-01-12 21:15:35 +0000350 register unsigned long long int _zzq_result __asm__("r3"); \
351 register unsigned long long int* _zzq_ptr __asm__("r4"); \
352 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
353 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
354 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
355 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
356 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000357 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000358 _zzq_ptr = _zzq_args; \
sewardj1a85f4f2006-01-12 21:15:35 +0000359 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
360 /* %R3 = client_request ( %R4 ) */ \
361 "or 1,1,1" \
362 : "=r" (_zzq_result) \
sewardj0ec07f32006-01-12 12:32:32 +0000363 : "0" (_zzq_default), "r" (_zzq_ptr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000364 : "cc", "memory"); \
365 _zzq_rlval = _zzq_result; \
sewardj0ec07f32006-01-12 12:32:32 +0000366 }
sewardj1a85f4f2006-01-12 21:15:35 +0000367
sewardjd68ac3e2006-01-20 14:31:57 +0000368#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
369 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
370 register unsigned long long int __addr __asm__("r3"); \
sewardj1a85f4f2006-01-12 21:15:35 +0000371 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
372 /* %R3 = guest_NRADDR */ \
373 "or 2,2,2" \
374 : "=r" (__addr) \
375 : \
376 : "cc", "memory" \
377 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000378 _zzq_orig->nraddr = __addr; \
379 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
380 /* %R3 = guest_NRADDR_GPR2 */ \
381 "or 4,4,4" \
382 : "=r" (__addr) \
383 : \
384 : "cc", "memory" \
385 ); \
386 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000387 }
388
389#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
390 __SPECIAL_INSTRUCTION_PREAMBLE \
391 /* branch-and-link-to-noredir *%R11 */ \
392 "or 3,3,3\n\t"
393
sewardj0ec07f32006-01-12 12:32:32 +0000394#endif /* ARCH_ppc64 */
cerion85665ca2005-06-20 15:51:07 +0000395
njn3dd0a912005-06-28 19:44:10 +0000396/* Insert assembly code for other architectures here... */
njn26aba4d2005-05-16 13:31:23 +0000397
sewardj37091fb2002-11-16 11:06:50 +0000398#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +0000399
nethercote69d9c462004-10-26 13:00:12 +0000400
njn30d76c62005-06-18 15:07:39 +0000401/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000402/* ARCHITECTURE SPECIFICS for FUNCTION WRAPPING. This is all very */
403/* ugly. It's the least-worst tradeoff I can think of. */
404/* ------------------------------------------------------------------ */
405
406/* This section defines magic (a.k.a appalling-hack) macros for doing
407 guaranteed-no-redirection macros, so as to get from function
408 wrappers to the functions they are wrapping. The whole point is to
409 construct standard call sequences, but to do the call itself with a
410 special no-redirect call pseudo-instruction that the JIT
411 understands and handles specially. This section is long and
412 repetitious, and I can't see a way to make it shorter.
413
414 The naming scheme is as follows:
415
416 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
417
418 'W' stands for "word" and 'v' for "void". Hence there are
419 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
420 and for each, the possibility of returning a word-typed result, or
421 no result.
422*/
423
424/* Use these to write the name of your wrapper. NOTE: duplicates
425 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
426
427#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
428 _vgwZU_##soname##_##fnname
429
430#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
431 _vgwZZ_##soname##_##fnname
432
sewardjd68ac3e2006-01-20 14:31:57 +0000433/* Use this macro from within a wrapper function to collect the
434 context (address and possibly other info) of the original function.
435 Once you have that you can then use it in one of the CALL_FN_
436 macros. The type of the argument _lval is OrigFn. */
437#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +0000438
439/* Derivatives of the main macros below, for calling functions
440 returning void. */
441
442#define CALL_FN_v_v(fnptr) \
443 do { volatile unsigned long _junk; \
444 CALL_FN_W_v(_junk,fnptr); } while (0)
445
446#define CALL_FN_v_W(fnptr, arg1) \
447 do { volatile unsigned long _junk; \
448 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
449
450#define CALL_FN_v_WW(fnptr, arg1,arg2) \
451 do { volatile unsigned long _junk; \
452 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
453
sewardj5ce4b152006-03-11 12:57:41 +0000454#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
455 do { volatile unsigned long _junk; \
456 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
457
sewardj0ec07f32006-01-12 12:32:32 +0000458/* ---------------------------- x86 ---------------------------- */
459
460#if defined(ARCH_x86)
461
462/* These regs are trashed by the hidden call. No need to mention eax
463 as gcc can already see that, plus causes gcc to bomb. */
464#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
465
466/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
467 long) == 4. */
468
sewardj66226cc2006-01-20 15:46:46 +0000469#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +0000470 do { \
sewardj66226cc2006-01-20 15:46:46 +0000471 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000472 volatile unsigned long _argvec[1]; \
473 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000474 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000475 __asm__ volatile( \
476 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
477 VALGRIND_CALL_NOREDIR_EAX \
478 : /*out*/ "=a" (_res) \
479 : /*in*/ "a" (&_argvec[0]) \
480 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
481 ); \
482 lval = (__typeof__(lval)) _res; \
483 } while (0)
484
sewardj66226cc2006-01-20 15:46:46 +0000485#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +0000486 do { \
sewardj66226cc2006-01-20 15:46:46 +0000487 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000488 volatile unsigned long _argvec[2]; \
489 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000490 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000491 _argvec[1] = (unsigned long)(arg1); \
492 __asm__ volatile( \
493 "pushl 4(%%eax)\n\t" \
494 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
495 VALGRIND_CALL_NOREDIR_EAX \
496 "addl $4, %%esp\n" \
497 : /*out*/ "=a" (_res) \
498 : /*in*/ "a" (&_argvec[0]) \
499 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
500 ); \
501 lval = (__typeof__(lval)) _res; \
502 } while (0)
503
sewardj66226cc2006-01-20 15:46:46 +0000504#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +0000505 do { \
sewardj66226cc2006-01-20 15:46:46 +0000506 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000507 volatile unsigned long _argvec[3]; \
508 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000509 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000510 _argvec[1] = (unsigned long)(arg1); \
511 _argvec[2] = (unsigned long)(arg2); \
512 __asm__ volatile( \
513 "pushl 8(%%eax)\n\t" \
514 "pushl 4(%%eax)\n\t" \
515 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
516 VALGRIND_CALL_NOREDIR_EAX \
517 "addl $8, %%esp\n" \
518 : /*out*/ "=a" (_res) \
519 : /*in*/ "a" (&_argvec[0]) \
520 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
521 ); \
522 lval = (__typeof__(lval)) _res; \
523 } while (0)
524
sewardj9e8b07a2006-02-18 21:13:29 +0000525#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
526 do { \
527 volatile OrigFn _orig = (orig); \
528 volatile unsigned long _argvec[4]; \
529 volatile unsigned long _res; \
530 _argvec[0] = (unsigned long)_orig.nraddr; \
531 _argvec[1] = (unsigned long)(arg1); \
532 _argvec[2] = (unsigned long)(arg2); \
533 _argvec[3] = (unsigned long)(arg3); \
534 __asm__ volatile( \
535 "pushl 12(%%eax)\n\t" \
536 "pushl 8(%%eax)\n\t" \
537 "pushl 4(%%eax)\n\t" \
538 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
539 VALGRIND_CALL_NOREDIR_EAX \
540 "addl $12, %%esp\n" \
541 : /*out*/ "=a" (_res) \
542 : /*in*/ "a" (&_argvec[0]) \
543 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
544 ); \
545 lval = (__typeof__(lval)) _res; \
546 } while (0)
547
sewardj66226cc2006-01-20 15:46:46 +0000548#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
sewardj0ec07f32006-01-12 12:32:32 +0000549 do { \
sewardj66226cc2006-01-20 15:46:46 +0000550 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000551 volatile unsigned long _argvec[5]; \
552 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000553 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000554 _argvec[1] = (unsigned long)(arg1); \
555 _argvec[2] = (unsigned long)(arg2); \
556 _argvec[3] = (unsigned long)(arg3); \
557 _argvec[4] = (unsigned long)(arg4); \
558 __asm__ volatile( \
559 "pushl 16(%%eax)\n\t" \
560 "pushl 12(%%eax)\n\t" \
561 "pushl 8(%%eax)\n\t" \
562 "pushl 4(%%eax)\n\t" \
563 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
564 VALGRIND_CALL_NOREDIR_EAX \
565 "addl $16, %%esp\n" \
566 : /*out*/ "=a" (_res) \
567 : /*in*/ "a" (&_argvec[0]) \
568 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
569 ); \
570 lval = (__typeof__(lval)) _res; \
571 } while (0)
572
sewardj66226cc2006-01-20 15:46:46 +0000573#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000574 do { \
sewardj66226cc2006-01-20 15:46:46 +0000575 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000576 volatile unsigned long _argvec[6]; \
577 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000578 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000579 _argvec[1] = (unsigned long)(arg1); \
580 _argvec[2] = (unsigned long)(arg2); \
581 _argvec[3] = (unsigned long)(arg3); \
582 _argvec[4] = (unsigned long)(arg4); \
583 _argvec[5] = (unsigned long)(arg5); \
584 __asm__ volatile( \
585 "pushl 20(%%eax)\n\t" \
586 "pushl 16(%%eax)\n\t" \
587 "pushl 12(%%eax)\n\t" \
588 "pushl 8(%%eax)\n\t" \
589 "pushl 4(%%eax)\n\t" \
590 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
591 VALGRIND_CALL_NOREDIR_EAX \
592 "addl $20, %%esp\n" \
593 : /*out*/ "=a" (_res) \
594 : /*in*/ "a" (&_argvec[0]) \
595 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
596 ); \
597 lval = (__typeof__(lval)) _res; \
598 } while (0)
599
sewardj66226cc2006-01-20 15:46:46 +0000600#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +0000601 do { \
sewardj66226cc2006-01-20 15:46:46 +0000602 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000603 volatile unsigned long _argvec[7]; \
604 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000605 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000606 _argvec[1] = (unsigned long)(arg1); \
607 _argvec[2] = (unsigned long)(arg2); \
608 _argvec[3] = (unsigned long)(arg3); \
609 _argvec[4] = (unsigned long)(arg4); \
610 _argvec[5] = (unsigned long)(arg5); \
611 _argvec[6] = (unsigned long)(arg6); \
612 __asm__ volatile( \
613 "pushl 24(%%eax)\n\t" \
614 "pushl 20(%%eax)\n\t" \
615 "pushl 16(%%eax)\n\t" \
616 "pushl 12(%%eax)\n\t" \
617 "pushl 8(%%eax)\n\t" \
618 "pushl 4(%%eax)\n\t" \
619 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
620 VALGRIND_CALL_NOREDIR_EAX \
621 "addl $24, %%esp\n" \
622 : /*out*/ "=a" (_res) \
623 : /*in*/ "a" (&_argvec[0]) \
624 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
625 ); \
626 lval = (__typeof__(lval)) _res; \
627 } while (0)
628
sewardj66226cc2006-01-20 15:46:46 +0000629#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
630 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +0000631 do { \
sewardj66226cc2006-01-20 15:46:46 +0000632 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000633 volatile unsigned long _argvec[8]; \
634 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000635 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000636 _argvec[1] = (unsigned long)(arg1); \
637 _argvec[2] = (unsigned long)(arg2); \
638 _argvec[3] = (unsigned long)(arg3); \
639 _argvec[4] = (unsigned long)(arg4); \
640 _argvec[5] = (unsigned long)(arg5); \
641 _argvec[6] = (unsigned long)(arg6); \
642 _argvec[7] = (unsigned long)(arg7); \
643 __asm__ volatile( \
644 "pushl 28(%%eax)\n\t" \
645 "pushl 24(%%eax)\n\t" \
646 "pushl 20(%%eax)\n\t" \
647 "pushl 16(%%eax)\n\t" \
648 "pushl 12(%%eax)\n\t" \
649 "pushl 8(%%eax)\n\t" \
650 "pushl 4(%%eax)\n\t" \
651 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
652 VALGRIND_CALL_NOREDIR_EAX \
653 "addl $28, %%esp\n" \
654 : /*out*/ "=a" (_res) \
655 : /*in*/ "a" (&_argvec[0]) \
656 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
657 ); \
658 lval = (__typeof__(lval)) _res; \
659 } while (0)
660
sewardj66226cc2006-01-20 15:46:46 +0000661#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
662 arg7,arg8) \
sewardj0ec07f32006-01-12 12:32:32 +0000663 do { \
sewardj66226cc2006-01-20 15:46:46 +0000664 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000665 volatile unsigned long _argvec[9]; \
666 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000667 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000668 _argvec[1] = (unsigned long)(arg1); \
669 _argvec[2] = (unsigned long)(arg2); \
670 _argvec[3] = (unsigned long)(arg3); \
671 _argvec[4] = (unsigned long)(arg4); \
672 _argvec[5] = (unsigned long)(arg5); \
673 _argvec[6] = (unsigned long)(arg6); \
674 _argvec[7] = (unsigned long)(arg7); \
675 _argvec[8] = (unsigned long)(arg8); \
676 __asm__ volatile( \
677 "pushl 32(%%eax)\n\t" \
678 "pushl 28(%%eax)\n\t" \
679 "pushl 24(%%eax)\n\t" \
680 "pushl 20(%%eax)\n\t" \
681 "pushl 16(%%eax)\n\t" \
682 "pushl 12(%%eax)\n\t" \
683 "pushl 8(%%eax)\n\t" \
684 "pushl 4(%%eax)\n\t" \
685 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
686 VALGRIND_CALL_NOREDIR_EAX \
687 "addl $32, %%esp\n" \
688 : /*out*/ "=a" (_res) \
689 : /*in*/ "a" (&_argvec[0]) \
690 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
691 ); \
692 lval = (__typeof__(lval)) _res; \
693 } while (0)
694
sewardj45fa5b02006-03-09 19:06:23 +0000695#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
696 arg7,arg8,arg9) \
697 do { \
698 volatile OrigFn _orig = (orig); \
699 volatile unsigned long _argvec[10]; \
700 volatile unsigned long _res; \
701 _argvec[0] = (unsigned long)_orig.nraddr; \
702 _argvec[1] = (unsigned long)(arg1); \
703 _argvec[2] = (unsigned long)(arg2); \
704 _argvec[3] = (unsigned long)(arg3); \
705 _argvec[4] = (unsigned long)(arg4); \
706 _argvec[5] = (unsigned long)(arg5); \
707 _argvec[6] = (unsigned long)(arg6); \
708 _argvec[7] = (unsigned long)(arg7); \
709 _argvec[8] = (unsigned long)(arg8); \
710 _argvec[9] = (unsigned long)(arg9); \
711 __asm__ volatile( \
712 "pushl 36(%%eax)\n\t" \
713 "pushl 32(%%eax)\n\t" \
714 "pushl 28(%%eax)\n\t" \
715 "pushl 24(%%eax)\n\t" \
716 "pushl 20(%%eax)\n\t" \
717 "pushl 16(%%eax)\n\t" \
718 "pushl 12(%%eax)\n\t" \
719 "pushl 8(%%eax)\n\t" \
720 "pushl 4(%%eax)\n\t" \
721 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
722 VALGRIND_CALL_NOREDIR_EAX \
723 "addl $36, %%esp\n" \
724 : /*out*/ "=a" (_res) \
725 : /*in*/ "a" (&_argvec[0]) \
726 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
727 ); \
728 lval = (__typeof__(lval)) _res; \
729 } while (0)
730
731#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
732 arg7,arg8,arg9,arg10) \
733 do { \
734 volatile OrigFn _orig = (orig); \
735 volatile unsigned long _argvec[11]; \
736 volatile unsigned long _res; \
737 _argvec[0] = (unsigned long)_orig.nraddr; \
738 _argvec[1] = (unsigned long)(arg1); \
739 _argvec[2] = (unsigned long)(arg2); \
740 _argvec[3] = (unsigned long)(arg3); \
741 _argvec[4] = (unsigned long)(arg4); \
742 _argvec[5] = (unsigned long)(arg5); \
743 _argvec[6] = (unsigned long)(arg6); \
744 _argvec[7] = (unsigned long)(arg7); \
745 _argvec[8] = (unsigned long)(arg8); \
746 _argvec[9] = (unsigned long)(arg9); \
747 _argvec[10] = (unsigned long)(arg10); \
748 __asm__ volatile( \
749 "pushl 40(%%eax)\n\t" \
750 "pushl 36(%%eax)\n\t" \
751 "pushl 32(%%eax)\n\t" \
752 "pushl 28(%%eax)\n\t" \
753 "pushl 24(%%eax)\n\t" \
754 "pushl 20(%%eax)\n\t" \
755 "pushl 16(%%eax)\n\t" \
756 "pushl 12(%%eax)\n\t" \
757 "pushl 8(%%eax)\n\t" \
758 "pushl 4(%%eax)\n\t" \
759 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
760 VALGRIND_CALL_NOREDIR_EAX \
761 "addl $40, %%esp\n" \
762 : /*out*/ "=a" (_res) \
763 : /*in*/ "a" (&_argvec[0]) \
764 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
765 ); \
766 lval = (__typeof__(lval)) _res; \
767 } while (0)
768
sewardj5ce4b152006-03-11 12:57:41 +0000769#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
770 arg6,arg7,arg8,arg9,arg10, \
771 arg11) \
772 do { \
773 volatile OrigFn _orig = (orig); \
774 volatile unsigned long _argvec[12]; \
775 volatile unsigned long _res; \
776 _argvec[0] = (unsigned long)_orig.nraddr; \
777 _argvec[1] = (unsigned long)(arg1); \
778 _argvec[2] = (unsigned long)(arg2); \
779 _argvec[3] = (unsigned long)(arg3); \
780 _argvec[4] = (unsigned long)(arg4); \
781 _argvec[5] = (unsigned long)(arg5); \
782 _argvec[6] = (unsigned long)(arg6); \
783 _argvec[7] = (unsigned long)(arg7); \
784 _argvec[8] = (unsigned long)(arg8); \
785 _argvec[9] = (unsigned long)(arg9); \
786 _argvec[10] = (unsigned long)(arg10); \
787 _argvec[11] = (unsigned long)(arg11); \
788 __asm__ volatile( \
789 "pushl 44(%%eax)\n\t" \
790 "pushl 40(%%eax)\n\t" \
791 "pushl 36(%%eax)\n\t" \
792 "pushl 32(%%eax)\n\t" \
793 "pushl 28(%%eax)\n\t" \
794 "pushl 24(%%eax)\n\t" \
795 "pushl 20(%%eax)\n\t" \
796 "pushl 16(%%eax)\n\t" \
797 "pushl 12(%%eax)\n\t" \
798 "pushl 8(%%eax)\n\t" \
799 "pushl 4(%%eax)\n\t" \
800 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
801 VALGRIND_CALL_NOREDIR_EAX \
802 "addl $44, %%esp\n" \
803 : /*out*/ "=a" (_res) \
804 : /*in*/ "a" (&_argvec[0]) \
805 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
806 ); \
807 lval = (__typeof__(lval)) _res; \
808 } while (0)
809
sewardj66226cc2006-01-20 15:46:46 +0000810#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
811 arg6,arg7,arg8,arg9,arg10, \
812 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +0000813 do { \
sewardj66226cc2006-01-20 15:46:46 +0000814 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000815 volatile unsigned long _argvec[13]; \
816 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000817 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000818 _argvec[1] = (unsigned long)(arg1); \
819 _argvec[2] = (unsigned long)(arg2); \
820 _argvec[3] = (unsigned long)(arg3); \
821 _argvec[4] = (unsigned long)(arg4); \
822 _argvec[5] = (unsigned long)(arg5); \
823 _argvec[6] = (unsigned long)(arg6); \
824 _argvec[7] = (unsigned long)(arg7); \
825 _argvec[8] = (unsigned long)(arg8); \
826 _argvec[9] = (unsigned long)(arg9); \
827 _argvec[10] = (unsigned long)(arg10); \
828 _argvec[11] = (unsigned long)(arg11); \
829 _argvec[12] = (unsigned long)(arg12); \
830 __asm__ volatile( \
831 "pushl 48(%%eax)\n\t" \
832 "pushl 44(%%eax)\n\t" \
833 "pushl 40(%%eax)\n\t" \
834 "pushl 36(%%eax)\n\t" \
835 "pushl 32(%%eax)\n\t" \
836 "pushl 28(%%eax)\n\t" \
837 "pushl 24(%%eax)\n\t" \
838 "pushl 20(%%eax)\n\t" \
839 "pushl 16(%%eax)\n\t" \
840 "pushl 12(%%eax)\n\t" \
841 "pushl 8(%%eax)\n\t" \
842 "pushl 4(%%eax)\n\t" \
843 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
844 VALGRIND_CALL_NOREDIR_EAX \
845 "addl $48, %%esp\n" \
846 : /*out*/ "=a" (_res) \
847 : /*in*/ "a" (&_argvec[0]) \
848 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
849 ); \
850 lval = (__typeof__(lval)) _res; \
851 } while (0)
852
853#endif /* ARCH_x86 */
854
855/* --------------------------- amd64 --------------------------- */
856
857#if defined(ARCH_amd64)
858
859/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
860
861/* These regs are trashed by the hidden call. */
862#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
863 "rdi", "r8", "r9", "r10", "r11"
864
865/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
866 long) == 8. */
867
sewardjc8858442006-01-20 15:17:20 +0000868#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +0000869 do { \
sewardjc8858442006-01-20 15:17:20 +0000870 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000871 volatile unsigned long _argvec[1]; \
872 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +0000873 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000874 __asm__ volatile( \
875 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
876 VALGRIND_CALL_NOREDIR_RAX \
877 : /*out*/ "=a" (_res) \
878 : /*in*/ "a" (&_argvec[0]) \
879 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
880 ); \
881 lval = (__typeof__(lval)) _res; \
882 } while (0)
883
sewardjc8858442006-01-20 15:17:20 +0000884#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +0000885 do { \
sewardjc8858442006-01-20 15:17:20 +0000886 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000887 volatile unsigned long _argvec[2]; \
888 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +0000889 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000890 _argvec[1] = (unsigned long)(arg1); \
891 __asm__ volatile( \
892 "movq 8(%%rax), %%rdi\n\t" \
893 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
894 VALGRIND_CALL_NOREDIR_RAX \
895 : /*out*/ "=a" (_res) \
896 : /*in*/ "a" (&_argvec[0]) \
897 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
898 ); \
899 lval = (__typeof__(lval)) _res; \
900 } while (0)
901
sewardjc8858442006-01-20 15:17:20 +0000902#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +0000903 do { \
sewardjc8858442006-01-20 15:17:20 +0000904 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000905 volatile unsigned long _argvec[3]; \
906 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +0000907 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000908 _argvec[1] = (unsigned long)(arg1); \
909 _argvec[2] = (unsigned long)(arg2); \
910 __asm__ volatile( \
911 "movq 16(%%rax), %%rsi\n\t" \
912 "movq 8(%%rax), %%rdi\n\t" \
913 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
914 VALGRIND_CALL_NOREDIR_RAX \
915 : /*out*/ "=a" (_res) \
916 : /*in*/ "a" (&_argvec[0]) \
917 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
918 ); \
919 lval = (__typeof__(lval)) _res; \
920 } while (0)
921
sewardja50f9dc2006-03-11 16:19:14 +0000922#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
923 do { \
924 volatile OrigFn _orig = (orig); \
925 volatile unsigned long _argvec[4]; \
926 volatile unsigned long _res; \
927 _argvec[0] = (unsigned long)_orig.nraddr; \
928 _argvec[1] = (unsigned long)(arg1); \
929 _argvec[2] = (unsigned long)(arg2); \
930 _argvec[3] = (unsigned long)(arg3); \
931 __asm__ volatile( \
932 "movq 24(%%rax), %%rdx\n\t" \
933 "movq 16(%%rax), %%rsi\n\t" \
934 "movq 8(%%rax), %%rdi\n\t" \
935 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
936 VALGRIND_CALL_NOREDIR_RAX \
937 : /*out*/ "=a" (_res) \
938 : /*in*/ "a" (&_argvec[0]) \
939 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
940 ); \
941 lval = (__typeof__(lval)) _res; \
942 } while (0)
943
944#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
945 do { \
946 volatile OrigFn _orig = (orig); \
947 volatile unsigned long _argvec[5]; \
948 volatile unsigned long _res; \
949 _argvec[0] = (unsigned long)_orig.nraddr; \
950 _argvec[1] = (unsigned long)(arg1); \
951 _argvec[2] = (unsigned long)(arg2); \
952 _argvec[3] = (unsigned long)(arg3); \
953 _argvec[4] = (unsigned long)(arg4); \
954 __asm__ volatile( \
955 "movq 32(%%rax), %%rcx\n\t" \
956 "movq 24(%%rax), %%rdx\n\t" \
957 "movq 16(%%rax), %%rsi\n\t" \
958 "movq 8(%%rax), %%rdi\n\t" \
959 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
960 VALGRIND_CALL_NOREDIR_RAX \
961 : /*out*/ "=a" (_res) \
962 : /*in*/ "a" (&_argvec[0]) \
963 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
964 ); \
965 lval = (__typeof__(lval)) _res; \
966 } while (0)
967
968#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
969 do { \
970 volatile OrigFn _orig = (orig); \
971 volatile unsigned long _argvec[6]; \
972 volatile unsigned long _res; \
973 _argvec[0] = (unsigned long)_orig.nraddr; \
974 _argvec[1] = (unsigned long)(arg1); \
975 _argvec[2] = (unsigned long)(arg2); \
976 _argvec[3] = (unsigned long)(arg3); \
977 _argvec[4] = (unsigned long)(arg4); \
978 _argvec[5] = (unsigned long)(arg5); \
979 __asm__ volatile( \
980 "movq 40(%%rax), %%r8\n\t" \
981 "movq 32(%%rax), %%rcx\n\t" \
982 "movq 24(%%rax), %%rdx\n\t" \
983 "movq 16(%%rax), %%rsi\n\t" \
984 "movq 8(%%rax), %%rdi\n\t" \
985 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
986 VALGRIND_CALL_NOREDIR_RAX \
987 : /*out*/ "=a" (_res) \
988 : /*in*/ "a" (&_argvec[0]) \
989 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
990 ); \
991 lval = (__typeof__(lval)) _res; \
992 } while (0)
993
994#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
995 do { \
996 volatile OrigFn _orig = (orig); \
997 volatile unsigned long _argvec[7]; \
998 volatile unsigned long _res; \
999 _argvec[0] = (unsigned long)_orig.nraddr; \
1000 _argvec[1] = (unsigned long)(arg1); \
1001 _argvec[2] = (unsigned long)(arg2); \
1002 _argvec[3] = (unsigned long)(arg3); \
1003 _argvec[4] = (unsigned long)(arg4); \
1004 _argvec[5] = (unsigned long)(arg5); \
1005 _argvec[6] = (unsigned long)(arg6); \
1006 __asm__ volatile( \
1007 "movq 48(%%rax), %%r9\n\t" \
1008 "movq 40(%%rax), %%r8\n\t" \
1009 "movq 32(%%rax), %%rcx\n\t" \
1010 "movq 24(%%rax), %%rdx\n\t" \
1011 "movq 16(%%rax), %%rsi\n\t" \
1012 "movq 8(%%rax), %%rdi\n\t" \
1013 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1014 VALGRIND_CALL_NOREDIR_RAX \
1015 : /*out*/ "=a" (_res) \
1016 : /*in*/ "a" (&_argvec[0]) \
1017 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1018 ); \
1019 lval = (__typeof__(lval)) _res; \
1020 } while (0)
1021
1022#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1023 arg7) \
1024 do { \
1025 volatile OrigFn _orig = (orig); \
1026 volatile unsigned long _argvec[8]; \
1027 volatile unsigned long _res; \
1028 _argvec[0] = (unsigned long)_orig.nraddr; \
1029 _argvec[1] = (unsigned long)(arg1); \
1030 _argvec[2] = (unsigned long)(arg2); \
1031 _argvec[3] = (unsigned long)(arg3); \
1032 _argvec[4] = (unsigned long)(arg4); \
1033 _argvec[5] = (unsigned long)(arg5); \
1034 _argvec[6] = (unsigned long)(arg6); \
1035 _argvec[7] = (unsigned long)(arg7); \
1036 __asm__ volatile( \
1037 "pushq 56(%%rax)\n\t" \
1038 "movq 48(%%rax), %%r9\n\t" \
1039 "movq 40(%%rax), %%r8\n\t" \
1040 "movq 32(%%rax), %%rcx\n\t" \
1041 "movq 24(%%rax), %%rdx\n\t" \
1042 "movq 16(%%rax), %%rsi\n\t" \
1043 "movq 8(%%rax), %%rdi\n\t" \
1044 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1045 VALGRIND_CALL_NOREDIR_RAX \
1046 "addq $8, %%rsp\n" \
1047 : /*out*/ "=a" (_res) \
1048 : /*in*/ "a" (&_argvec[0]) \
1049 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1050 ); \
1051 lval = (__typeof__(lval)) _res; \
1052 } while (0)
1053
1054#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1055 arg7,arg8) \
1056 do { \
1057 volatile OrigFn _orig = (orig); \
1058 volatile unsigned long _argvec[9]; \
1059 volatile unsigned long _res; \
1060 _argvec[0] = (unsigned long)_orig.nraddr; \
1061 _argvec[1] = (unsigned long)(arg1); \
1062 _argvec[2] = (unsigned long)(arg2); \
1063 _argvec[3] = (unsigned long)(arg3); \
1064 _argvec[4] = (unsigned long)(arg4); \
1065 _argvec[5] = (unsigned long)(arg5); \
1066 _argvec[6] = (unsigned long)(arg6); \
1067 _argvec[7] = (unsigned long)(arg7); \
1068 _argvec[8] = (unsigned long)(arg8); \
1069 __asm__ volatile( \
1070 "pushq 64(%%rax)\n\t" \
1071 "pushq 56(%%rax)\n\t" \
1072 "movq 48(%%rax), %%r9\n\t" \
1073 "movq 40(%%rax), %%r8\n\t" \
1074 "movq 32(%%rax), %%rcx\n\t" \
1075 "movq 24(%%rax), %%rdx\n\t" \
1076 "movq 16(%%rax), %%rsi\n\t" \
1077 "movq 8(%%rax), %%rdi\n\t" \
1078 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1079 VALGRIND_CALL_NOREDIR_RAX \
1080 "addq $16, %%rsp\n" \
1081 : /*out*/ "=a" (_res) \
1082 : /*in*/ "a" (&_argvec[0]) \
1083 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1084 ); \
1085 lval = (__typeof__(lval)) _res; \
1086 } while (0)
1087
1088#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1089 arg7,arg8,arg9) \
1090 do { \
1091 volatile OrigFn _orig = (orig); \
1092 volatile unsigned long _argvec[10]; \
1093 volatile unsigned long _res; \
1094 _argvec[0] = (unsigned long)_orig.nraddr; \
1095 _argvec[1] = (unsigned long)(arg1); \
1096 _argvec[2] = (unsigned long)(arg2); \
1097 _argvec[3] = (unsigned long)(arg3); \
1098 _argvec[4] = (unsigned long)(arg4); \
1099 _argvec[5] = (unsigned long)(arg5); \
1100 _argvec[6] = (unsigned long)(arg6); \
1101 _argvec[7] = (unsigned long)(arg7); \
1102 _argvec[8] = (unsigned long)(arg8); \
1103 _argvec[9] = (unsigned long)(arg9); \
1104 __asm__ volatile( \
1105 "pushq 72(%%rax)\n\t" \
1106 "pushq 64(%%rax)\n\t" \
1107 "pushq 56(%%rax)\n\t" \
1108 "movq 48(%%rax), %%r9\n\t" \
1109 "movq 40(%%rax), %%r8\n\t" \
1110 "movq 32(%%rax), %%rcx\n\t" \
1111 "movq 24(%%rax), %%rdx\n\t" \
1112 "movq 16(%%rax), %%rsi\n\t" \
1113 "movq 8(%%rax), %%rdi\n\t" \
1114 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1115 VALGRIND_CALL_NOREDIR_RAX \
1116 "addq $24, %%rsp\n" \
1117 : /*out*/ "=a" (_res) \
1118 : /*in*/ "a" (&_argvec[0]) \
1119 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1120 ); \
1121 lval = (__typeof__(lval)) _res; \
1122 } while (0)
1123
1124#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1125 arg7,arg8,arg9,arg10) \
1126 do { \
1127 volatile OrigFn _orig = (orig); \
1128 volatile unsigned long _argvec[11]; \
1129 volatile unsigned long _res; \
1130 _argvec[0] = (unsigned long)_orig.nraddr; \
1131 _argvec[1] = (unsigned long)(arg1); \
1132 _argvec[2] = (unsigned long)(arg2); \
1133 _argvec[3] = (unsigned long)(arg3); \
1134 _argvec[4] = (unsigned long)(arg4); \
1135 _argvec[5] = (unsigned long)(arg5); \
1136 _argvec[6] = (unsigned long)(arg6); \
1137 _argvec[7] = (unsigned long)(arg7); \
1138 _argvec[8] = (unsigned long)(arg8); \
1139 _argvec[9] = (unsigned long)(arg9); \
1140 _argvec[10] = (unsigned long)(arg10); \
1141 __asm__ volatile( \
1142 "pushq 80(%%rax)\n\t" \
1143 "pushq 72(%%rax)\n\t" \
1144 "pushq 64(%%rax)\n\t" \
1145 "pushq 56(%%rax)\n\t" \
1146 "movq 48(%%rax), %%r9\n\t" \
1147 "movq 40(%%rax), %%r8\n\t" \
1148 "movq 32(%%rax), %%rcx\n\t" \
1149 "movq 24(%%rax), %%rdx\n\t" \
1150 "movq 16(%%rax), %%rsi\n\t" \
1151 "movq 8(%%rax), %%rdi\n\t" \
1152 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1153 VALGRIND_CALL_NOREDIR_RAX \
1154 "addq $32, %%rsp\n" \
1155 : /*out*/ "=a" (_res) \
1156 : /*in*/ "a" (&_argvec[0]) \
1157 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1158 ); \
1159 lval = (__typeof__(lval)) _res; \
1160 } while (0)
1161
1162#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1163 arg7,arg8,arg9,arg10,arg11) \
1164 do { \
1165 volatile OrigFn _orig = (orig); \
1166 volatile unsigned long _argvec[12]; \
1167 volatile unsigned long _res; \
1168 _argvec[0] = (unsigned long)_orig.nraddr; \
1169 _argvec[1] = (unsigned long)(arg1); \
1170 _argvec[2] = (unsigned long)(arg2); \
1171 _argvec[3] = (unsigned long)(arg3); \
1172 _argvec[4] = (unsigned long)(arg4); \
1173 _argvec[5] = (unsigned long)(arg5); \
1174 _argvec[6] = (unsigned long)(arg6); \
1175 _argvec[7] = (unsigned long)(arg7); \
1176 _argvec[8] = (unsigned long)(arg8); \
1177 _argvec[9] = (unsigned long)(arg9); \
1178 _argvec[10] = (unsigned long)(arg10); \
1179 _argvec[11] = (unsigned long)(arg11); \
1180 __asm__ volatile( \
1181 "pushq 88(%%rax)\n\t" \
1182 "pushq 80(%%rax)\n\t" \
1183 "pushq 72(%%rax)\n\t" \
1184 "pushq 64(%%rax)\n\t" \
1185 "pushq 56(%%rax)\n\t" \
1186 "movq 48(%%rax), %%r9\n\t" \
1187 "movq 40(%%rax), %%r8\n\t" \
1188 "movq 32(%%rax), %%rcx\n\t" \
1189 "movq 24(%%rax), %%rdx\n\t" \
1190 "movq 16(%%rax), %%rsi\n\t" \
1191 "movq 8(%%rax), %%rdi\n\t" \
1192 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1193 VALGRIND_CALL_NOREDIR_RAX \
1194 "addq $40, %%rsp\n" \
1195 : /*out*/ "=a" (_res) \
1196 : /*in*/ "a" (&_argvec[0]) \
1197 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1198 ); \
1199 lval = (__typeof__(lval)) _res; \
1200 } while (0)
1201
1202#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1203 arg7,arg8,arg9,arg10,arg11,arg12) \
1204 do { \
1205 volatile OrigFn _orig = (orig); \
1206 volatile unsigned long _argvec[13]; \
1207 volatile unsigned long _res; \
1208 _argvec[0] = (unsigned long)_orig.nraddr; \
1209 _argvec[1] = (unsigned long)(arg1); \
1210 _argvec[2] = (unsigned long)(arg2); \
1211 _argvec[3] = (unsigned long)(arg3); \
1212 _argvec[4] = (unsigned long)(arg4); \
1213 _argvec[5] = (unsigned long)(arg5); \
1214 _argvec[6] = (unsigned long)(arg6); \
1215 _argvec[7] = (unsigned long)(arg7); \
1216 _argvec[8] = (unsigned long)(arg8); \
1217 _argvec[9] = (unsigned long)(arg9); \
1218 _argvec[10] = (unsigned long)(arg10); \
1219 _argvec[11] = (unsigned long)(arg11); \
1220 _argvec[12] = (unsigned long)(arg12); \
1221 __asm__ volatile( \
1222 "pushq 96(%%rax)\n\t" \
1223 "pushq 88(%%rax)\n\t" \
1224 "pushq 80(%%rax)\n\t" \
1225 "pushq 72(%%rax)\n\t" \
1226 "pushq 64(%%rax)\n\t" \
1227 "pushq 56(%%rax)\n\t" \
1228 "movq 48(%%rax), %%r9\n\t" \
1229 "movq 40(%%rax), %%r8\n\t" \
1230 "movq 32(%%rax), %%rcx\n\t" \
1231 "movq 24(%%rax), %%rdx\n\t" \
1232 "movq 16(%%rax), %%rsi\n\t" \
1233 "movq 8(%%rax), %%rdi\n\t" \
1234 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1235 VALGRIND_CALL_NOREDIR_RAX \
1236 "addq $48, %%rsp\n" \
1237 : /*out*/ "=a" (_res) \
1238 : /*in*/ "a" (&_argvec[0]) \
1239 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1240 ); \
1241 lval = (__typeof__(lval)) _res; \
1242 } while (0)
1243
sewardj0ec07f32006-01-12 12:32:32 +00001244#endif /* ARCH_amd64 */
1245
1246/* --------------------------- ppc32 --------------------------- */
1247
1248#if defined(ARCH_ppc32)
1249
sewardjead61df2006-03-12 13:39:15 +00001250/* This is useful for finding out about the on-stack stuff:
1251
1252 extern int f9 ( int,int,int,int,int,int,int,int,int );
1253 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1254 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1255 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1256
1257 int g9 ( void ) {
1258 return f9(11,22,33,44,55,66,77,88,99);
1259 }
1260 int g10 ( void ) {
1261 return f10(11,22,33,44,55,66,77,88,99,110);
1262 }
1263 int g11 ( void ) {
1264 return f11(11,22,33,44,55,66,77,88,99,110,121);
1265 }
1266 int g12 ( void ) {
1267 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1268 }
1269*/
1270
sewardj0ec07f32006-01-12 12:32:32 +00001271/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1272
1273/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00001274#define __CALLER_SAVED_REGS \
1275 "lr", "ctr", "xer", \
1276 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1277 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1278 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00001279
sewardjead61df2006-03-12 13:39:15 +00001280/* These CALL_FN_ macros assume that on ppc32-linux,
1281 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00001282
sewardj38de0992006-01-20 16:46:34 +00001283#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001284 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001285 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001286 volatile unsigned long _argvec[1]; \
1287 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001288 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001289 __asm__ volatile( \
1290 "mr 11,%1\n\t" \
1291 "lwz 11,0(11)\n\t" /* target->r11 */ \
1292 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1293 "mr %0,3" \
1294 : /*out*/ "=r" (_res) \
1295 : /*in*/ "r" (&_argvec[0]) \
1296 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1297 ); \
1298 lval = (__typeof__(lval)) _res; \
1299 } while (0)
1300
sewardj38de0992006-01-20 16:46:34 +00001301#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001302 do { \
sewardj38de0992006-01-20 16:46:34 +00001303 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001304 volatile unsigned long _argvec[2]; \
1305 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001306 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001307 _argvec[1] = (unsigned long)arg1; \
1308 __asm__ volatile( \
1309 "mr 11,%1\n\t" \
1310 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1311 "lwz 11,0(11)\n\t" /* target->r11 */ \
1312 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1313 "mr %0,3" \
1314 : /*out*/ "=r" (_res) \
1315 : /*in*/ "r" (&_argvec[0]) \
1316 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1317 ); \
1318 lval = (__typeof__(lval)) _res; \
1319 } while (0)
1320
sewardj38de0992006-01-20 16:46:34 +00001321#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001322 do { \
sewardj38de0992006-01-20 16:46:34 +00001323 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001324 volatile unsigned long _argvec[3]; \
1325 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001326 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001327 _argvec[1] = (unsigned long)arg1; \
1328 _argvec[2] = (unsigned long)arg2; \
1329 __asm__ volatile( \
1330 "mr 11,%1\n\t" \
1331 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1332 "lwz 4,8(11)\n\t" \
1333 "lwz 11,0(11)\n\t" /* target->r11 */ \
1334 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1335 "mr %0,3" \
1336 : /*out*/ "=r" (_res) \
1337 : /*in*/ "r" (&_argvec[0]) \
1338 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1339 ); \
1340 lval = (__typeof__(lval)) _res; \
1341 } while (0)
1342
sewardjead61df2006-03-12 13:39:15 +00001343#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1344 do { \
1345 volatile OrigFn _orig = (orig); \
1346 volatile unsigned long _argvec[4]; \
1347 volatile unsigned long _res; \
1348 _argvec[0] = (unsigned long)_orig.nraddr; \
1349 _argvec[1] = (unsigned long)arg1; \
1350 _argvec[2] = (unsigned long)arg2; \
1351 _argvec[3] = (unsigned long)arg3; \
1352 __asm__ volatile( \
1353 "mr 11,%1\n\t" \
1354 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1355 "lwz 4,8(11)\n\t" \
1356 "lwz 5,12(11)\n\t" \
1357 "lwz 11,0(11)\n\t" /* target->r11 */ \
1358 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1359 "mr %0,3" \
1360 : /*out*/ "=r" (_res) \
1361 : /*in*/ "r" (&_argvec[0]) \
1362 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1363 ); \
1364 lval = (__typeof__(lval)) _res; \
1365 } while (0)
1366
1367#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1368 do { \
1369 volatile OrigFn _orig = (orig); \
1370 volatile unsigned long _argvec[5]; \
1371 volatile unsigned long _res; \
1372 _argvec[0] = (unsigned long)_orig.nraddr; \
1373 _argvec[1] = (unsigned long)arg1; \
1374 _argvec[2] = (unsigned long)arg2; \
1375 _argvec[3] = (unsigned long)arg3; \
1376 _argvec[4] = (unsigned long)arg4; \
1377 __asm__ volatile( \
1378 "mr 11,%1\n\t" \
1379 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1380 "lwz 4,8(11)\n\t" \
1381 "lwz 5,12(11)\n\t" \
1382 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1383 "lwz 11,0(11)\n\t" /* target->r11 */ \
1384 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1385 "mr %0,3" \
1386 : /*out*/ "=r" (_res) \
1387 : /*in*/ "r" (&_argvec[0]) \
1388 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1389 ); \
1390 lval = (__typeof__(lval)) _res; \
1391 } while (0)
1392
1393#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1394 do { \
1395 volatile OrigFn _orig = (orig); \
1396 volatile unsigned long _argvec[6]; \
1397 volatile unsigned long _res; \
1398 _argvec[0] = (unsigned long)_orig.nraddr; \
1399 _argvec[1] = (unsigned long)arg1; \
1400 _argvec[2] = (unsigned long)arg2; \
1401 _argvec[3] = (unsigned long)arg3; \
1402 _argvec[4] = (unsigned long)arg4; \
1403 _argvec[5] = (unsigned long)arg5; \
1404 __asm__ volatile( \
1405 "mr 11,%1\n\t" \
1406 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1407 "lwz 4,8(11)\n\t" \
1408 "lwz 5,12(11)\n\t" \
1409 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1410 "lwz 7,20(11)\n\t" \
1411 "lwz 11,0(11)\n\t" /* target->r11 */ \
1412 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1413 "mr %0,3" \
1414 : /*out*/ "=r" (_res) \
1415 : /*in*/ "r" (&_argvec[0]) \
1416 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1417 ); \
1418 lval = (__typeof__(lval)) _res; \
1419 } while (0)
1420
1421#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1422 do { \
1423 volatile OrigFn _orig = (orig); \
1424 volatile unsigned long _argvec[7]; \
1425 volatile unsigned long _res; \
1426 _argvec[0] = (unsigned long)_orig.nraddr; \
1427 _argvec[1] = (unsigned long)arg1; \
1428 _argvec[2] = (unsigned long)arg2; \
1429 _argvec[3] = (unsigned long)arg3; \
1430 _argvec[4] = (unsigned long)arg4; \
1431 _argvec[5] = (unsigned long)arg5; \
1432 _argvec[6] = (unsigned long)arg6; \
1433 __asm__ volatile( \
1434 "mr 11,%1\n\t" \
1435 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1436 "lwz 4,8(11)\n\t" \
1437 "lwz 5,12(11)\n\t" \
1438 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1439 "lwz 7,20(11)\n\t" \
1440 "lwz 8,24(11)\n\t" \
1441 "lwz 11,0(11)\n\t" /* target->r11 */ \
1442 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1443 "mr %0,3" \
1444 : /*out*/ "=r" (_res) \
1445 : /*in*/ "r" (&_argvec[0]) \
1446 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1447 ); \
1448 lval = (__typeof__(lval)) _res; \
1449 } while (0)
1450
1451#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1452 arg7) \
1453 do { \
1454 volatile OrigFn _orig = (orig); \
1455 volatile unsigned long _argvec[8]; \
1456 volatile unsigned long _res; \
1457 _argvec[0] = (unsigned long)_orig.nraddr; \
1458 _argvec[1] = (unsigned long)arg1; \
1459 _argvec[2] = (unsigned long)arg2; \
1460 _argvec[3] = (unsigned long)arg3; \
1461 _argvec[4] = (unsigned long)arg4; \
1462 _argvec[5] = (unsigned long)arg5; \
1463 _argvec[6] = (unsigned long)arg6; \
1464 _argvec[7] = (unsigned long)arg7; \
1465 __asm__ volatile( \
1466 "mr 11,%1\n\t" \
1467 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1468 "lwz 4,8(11)\n\t" \
1469 "lwz 5,12(11)\n\t" \
1470 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1471 "lwz 7,20(11)\n\t" \
1472 "lwz 8,24(11)\n\t" \
1473 "lwz 9,28(11)\n\t" \
1474 "lwz 11,0(11)\n\t" /* target->r11 */ \
1475 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1476 "mr %0,3" \
1477 : /*out*/ "=r" (_res) \
1478 : /*in*/ "r" (&_argvec[0]) \
1479 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1480 ); \
1481 lval = (__typeof__(lval)) _res; \
1482 } while (0)
1483
1484#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1485 arg7,arg8) \
1486 do { \
1487 volatile OrigFn _orig = (orig); \
1488 volatile unsigned long _argvec[9]; \
1489 volatile unsigned long _res; \
1490 _argvec[0] = (unsigned long)_orig.nraddr; \
1491 _argvec[1] = (unsigned long)arg1; \
1492 _argvec[2] = (unsigned long)arg2; \
1493 _argvec[3] = (unsigned long)arg3; \
1494 _argvec[4] = (unsigned long)arg4; \
1495 _argvec[5] = (unsigned long)arg5; \
1496 _argvec[6] = (unsigned long)arg6; \
1497 _argvec[7] = (unsigned long)arg7; \
1498 _argvec[8] = (unsigned long)arg8; \
1499 __asm__ volatile( \
1500 "mr 11,%1\n\t" \
1501 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1502 "lwz 4,8(11)\n\t" \
1503 "lwz 5,12(11)\n\t" \
1504 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1505 "lwz 7,20(11)\n\t" \
1506 "lwz 8,24(11)\n\t" \
1507 "lwz 9,28(11)\n\t" \
1508 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1509 "lwz 11,0(11)\n\t" /* target->r11 */ \
1510 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1511 "mr %0,3" \
1512 : /*out*/ "=r" (_res) \
1513 : /*in*/ "r" (&_argvec[0]) \
1514 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1515 ); \
1516 lval = (__typeof__(lval)) _res; \
1517 } while (0)
1518
1519#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1520 arg7,arg8,arg9) \
1521 do { \
1522 volatile OrigFn _orig = (orig); \
1523 volatile unsigned long _argvec[10]; \
1524 volatile unsigned long _res; \
1525 _argvec[0] = (unsigned long)_orig.nraddr; \
1526 _argvec[1] = (unsigned long)arg1; \
1527 _argvec[2] = (unsigned long)arg2; \
1528 _argvec[3] = (unsigned long)arg3; \
1529 _argvec[4] = (unsigned long)arg4; \
1530 _argvec[5] = (unsigned long)arg5; \
1531 _argvec[6] = (unsigned long)arg6; \
1532 _argvec[7] = (unsigned long)arg7; \
1533 _argvec[8] = (unsigned long)arg8; \
1534 _argvec[9] = (unsigned long)arg9; \
1535 __asm__ volatile( \
1536 "mr 11,%1\n\t" \
1537 "addi 1,1,-16\n\t" \
1538 /* arg9 */ \
1539 "lwz 3,36(11)\n\t" \
1540 "stw 3,8(1)\n\t" \
1541 /* args1-8 */ \
1542 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1543 "lwz 4,8(11)\n\t" \
1544 "lwz 5,12(11)\n\t" \
1545 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1546 "lwz 7,20(11)\n\t" \
1547 "lwz 8,24(11)\n\t" \
1548 "lwz 9,28(11)\n\t" \
1549 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1550 "lwz 11,0(11)\n\t" /* target->r11 */ \
1551 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1552 "addi 1,1,16\n\t" \
1553 "mr %0,3" \
1554 : /*out*/ "=r" (_res) \
1555 : /*in*/ "r" (&_argvec[0]) \
1556 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1557 ); \
1558 lval = (__typeof__(lval)) _res; \
1559 } while (0)
1560
1561#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1562 arg7,arg8,arg9,arg10) \
1563 do { \
1564 volatile OrigFn _orig = (orig); \
1565 volatile unsigned long _argvec[11]; \
1566 volatile unsigned long _res; \
1567 _argvec[0] = (unsigned long)_orig.nraddr; \
1568 _argvec[1] = (unsigned long)arg1; \
1569 _argvec[2] = (unsigned long)arg2; \
1570 _argvec[3] = (unsigned long)arg3; \
1571 _argvec[4] = (unsigned long)arg4; \
1572 _argvec[5] = (unsigned long)arg5; \
1573 _argvec[6] = (unsigned long)arg6; \
1574 _argvec[7] = (unsigned long)arg7; \
1575 _argvec[8] = (unsigned long)arg8; \
1576 _argvec[9] = (unsigned long)arg9; \
1577 _argvec[10] = (unsigned long)arg10; \
1578 __asm__ volatile( \
1579 "mr 11,%1\n\t" \
1580 "addi 1,1,-16\n\t" \
1581 /* arg10 */ \
1582 "lwz 3,40(11)\n\t" \
1583 "stw 3,12(1)\n\t" \
1584 /* arg9 */ \
1585 "lwz 3,36(11)\n\t" \
1586 "stw 3,8(1)\n\t" \
1587 /* args1-8 */ \
1588 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1589 "lwz 4,8(11)\n\t" \
1590 "lwz 5,12(11)\n\t" \
1591 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1592 "lwz 7,20(11)\n\t" \
1593 "lwz 8,24(11)\n\t" \
1594 "lwz 9,28(11)\n\t" \
1595 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1596 "lwz 11,0(11)\n\t" /* target->r11 */ \
1597 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1598 "addi 1,1,16\n\t" \
1599 "mr %0,3" \
1600 : /*out*/ "=r" (_res) \
1601 : /*in*/ "r" (&_argvec[0]) \
1602 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1603 ); \
1604 lval = (__typeof__(lval)) _res; \
1605 } while (0)
1606
1607#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1608 arg7,arg8,arg9,arg10,arg11) \
1609 do { \
1610 volatile OrigFn _orig = (orig); \
1611 volatile unsigned long _argvec[12]; \
1612 volatile unsigned long _res; \
1613 _argvec[0] = (unsigned long)_orig.nraddr; \
1614 _argvec[1] = (unsigned long)arg1; \
1615 _argvec[2] = (unsigned long)arg2; \
1616 _argvec[3] = (unsigned long)arg3; \
1617 _argvec[4] = (unsigned long)arg4; \
1618 _argvec[5] = (unsigned long)arg5; \
1619 _argvec[6] = (unsigned long)arg6; \
1620 _argvec[7] = (unsigned long)arg7; \
1621 _argvec[8] = (unsigned long)arg8; \
1622 _argvec[9] = (unsigned long)arg9; \
1623 _argvec[10] = (unsigned long)arg10; \
1624 _argvec[11] = (unsigned long)arg11; \
1625 __asm__ volatile( \
1626 "mr 11,%1\n\t" \
1627 "addi 1,1,-32\n\t" \
1628 /* arg11 */ \
1629 "lwz 3,44(11)\n\t" \
1630 "stw 3,16(1)\n\t" \
1631 /* arg10 */ \
1632 "lwz 3,40(11)\n\t" \
1633 "stw 3,12(1)\n\t" \
1634 /* arg9 */ \
1635 "lwz 3,36(11)\n\t" \
1636 "stw 3,8(1)\n\t" \
1637 /* args1-8 */ \
1638 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1639 "lwz 4,8(11)\n\t" \
1640 "lwz 5,12(11)\n\t" \
1641 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1642 "lwz 7,20(11)\n\t" \
1643 "lwz 8,24(11)\n\t" \
1644 "lwz 9,28(11)\n\t" \
1645 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1646 "lwz 11,0(11)\n\t" /* target->r11 */ \
1647 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1648 "addi 1,1,32\n\t" \
1649 "mr %0,3" \
1650 : /*out*/ "=r" (_res) \
1651 : /*in*/ "r" (&_argvec[0]) \
1652 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1653 ); \
1654 lval = (__typeof__(lval)) _res; \
1655 } while (0)
1656
1657#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1658 arg7,arg8,arg9,arg10,arg11,arg12) \
1659 do { \
1660 volatile OrigFn _orig = (orig); \
1661 volatile unsigned long _argvec[13]; \
1662 volatile unsigned long _res; \
1663 _argvec[0] = (unsigned long)_orig.nraddr; \
1664 _argvec[1] = (unsigned long)arg1; \
1665 _argvec[2] = (unsigned long)arg2; \
1666 _argvec[3] = (unsigned long)arg3; \
1667 _argvec[4] = (unsigned long)arg4; \
1668 _argvec[5] = (unsigned long)arg5; \
1669 _argvec[6] = (unsigned long)arg6; \
1670 _argvec[7] = (unsigned long)arg7; \
1671 _argvec[8] = (unsigned long)arg8; \
1672 _argvec[9] = (unsigned long)arg9; \
1673 _argvec[10] = (unsigned long)arg10; \
1674 _argvec[11] = (unsigned long)arg11; \
1675 _argvec[12] = (unsigned long)arg12; \
1676 __asm__ volatile( \
1677 "mr 11,%1\n\t" \
1678 "addi 1,1,-32\n\t" \
1679 /* arg12 */ \
1680 "lwz 3,48(11)\n\t" \
1681 "stw 3,20(1)\n\t" \
1682 /* arg11 */ \
1683 "lwz 3,44(11)\n\t" \
1684 "stw 3,16(1)\n\t" \
1685 /* arg10 */ \
1686 "lwz 3,40(11)\n\t" \
1687 "stw 3,12(1)\n\t" \
1688 /* arg9 */ \
1689 "lwz 3,36(11)\n\t" \
1690 "stw 3,8(1)\n\t" \
1691 /* args1-8 */ \
1692 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1693 "lwz 4,8(11)\n\t" \
1694 "lwz 5,12(11)\n\t" \
1695 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1696 "lwz 7,20(11)\n\t" \
1697 "lwz 8,24(11)\n\t" \
1698 "lwz 9,28(11)\n\t" \
1699 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1700 "lwz 11,0(11)\n\t" /* target->r11 */ \
1701 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1702 "addi 1,1,32\n\t" \
1703 "mr %0,3" \
1704 : /*out*/ "=r" (_res) \
1705 : /*in*/ "r" (&_argvec[0]) \
1706 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1707 ); \
1708 lval = (__typeof__(lval)) _res; \
1709 } while (0)
1710
sewardj0ec07f32006-01-12 12:32:32 +00001711#endif /* ARCH_ppc32 */
1712
1713/* --------------------------- ppc64 --------------------------- */
1714
sewardj9734b202006-01-17 01:49:37 +00001715#if defined(ARCH_ppc64)
1716
1717/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1718
1719/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00001720#define __CALLER_SAVED_REGS \
1721 "lr", "ctr", "xer", \
1722 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1723 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1724 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00001725
1726/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
1727 long) == 8. */
1728
sewardjd68ac3e2006-01-20 14:31:57 +00001729#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00001730 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001731 volatile OrigFn _orig = (orig); \
1732 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00001733 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001734 /* _argvec[0] holds current r2 across the call */ \
1735 _argvec[1] = (unsigned long)_orig.r2; \
1736 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00001737 __asm__ volatile( \
1738 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001739 "std 2,-16(11)\n\t" /* save tocptr */ \
1740 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1741 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00001742 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1743 "mr 11,%1\n\t" \
1744 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001745 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00001746 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00001747 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00001748 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1749 ); \
1750 lval = (__typeof__(lval)) _res; \
1751 } while (0)
1752
sewardjd68ac3e2006-01-20 14:31:57 +00001753#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00001754 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001755 volatile OrigFn _orig = (orig); \
1756 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00001757 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001758 /* _argvec[0] holds current r2 across the call */ \
1759 _argvec[1] = (unsigned long)_orig.r2; \
1760 _argvec[2] = (unsigned long)_orig.nraddr; \
1761 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00001762 __asm__ volatile( \
1763 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001764 "std 2,-16(11)\n\t" /* save tocptr */ \
1765 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1766 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1767 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00001768 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1769 "mr 11,%1\n\t" \
1770 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001771 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00001772 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00001773 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00001774 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1775 ); \
1776 lval = (__typeof__(lval)) _res; \
1777 } while (0)
1778
sewardjd68ac3e2006-01-20 14:31:57 +00001779#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00001780 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001781 volatile OrigFn _orig = (orig); \
1782 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00001783 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001784 /* _argvec[0] holds current r2 across the call */ \
1785 _argvec[1] = (unsigned long)_orig.r2; \
1786 _argvec[2] = (unsigned long)_orig.nraddr; \
1787 _argvec[2+1] = (unsigned long)arg1; \
1788 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00001789 __asm__ volatile( \
1790 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001791 "std 2,-16(11)\n\t" /* save tocptr */ \
1792 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1793 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00001794 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00001795 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00001796 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1797 "mr 11,%1\n\t" \
1798 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001799 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00001800 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00001801 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00001802 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1803 ); \
1804 lval = (__typeof__(lval)) _res; \
1805 } while (0)
1806
sewardjcd636392006-03-12 16:48:14 +00001807#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1808 do { \
1809 volatile OrigFn _orig = (orig); \
1810 volatile unsigned long _argvec[3+3]; \
1811 volatile unsigned long _res; \
1812 /* _argvec[0] holds current r2 across the call */ \
1813 _argvec[1] = (unsigned long)_orig.r2; \
1814 _argvec[2] = (unsigned long)_orig.nraddr; \
1815 _argvec[2+1] = (unsigned long)arg1; \
1816 _argvec[2+2] = (unsigned long)arg2; \
1817 _argvec[2+3] = (unsigned long)arg3; \
1818 __asm__ volatile( \
1819 "mr 11,%1\n\t" \
1820 "std 2,-16(11)\n\t" /* save tocptr */ \
1821 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1822 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1823 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1824 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1825 "ld 11, 0(11)\n\t" /* target->r11 */ \
1826 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1827 "mr 11,%1\n\t" \
1828 "mr %0,3\n\t" \
1829 "ld 2,-16(11)" /* restore tocptr */ \
1830 : /*out*/ "=r" (_res) \
1831 : /*in*/ "r" (&_argvec[2]) \
1832 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1833 ); \
1834 lval = (__typeof__(lval)) _res; \
1835 } while (0)
1836
1837#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1838 do { \
1839 volatile OrigFn _orig = (orig); \
1840 volatile unsigned long _argvec[3+4]; \
1841 volatile unsigned long _res; \
1842 /* _argvec[0] holds current r2 across the call */ \
1843 _argvec[1] = (unsigned long)_orig.r2; \
1844 _argvec[2] = (unsigned long)_orig.nraddr; \
1845 _argvec[2+1] = (unsigned long)arg1; \
1846 _argvec[2+2] = (unsigned long)arg2; \
1847 _argvec[2+3] = (unsigned long)arg3; \
1848 _argvec[2+4] = (unsigned long)arg4; \
1849 __asm__ volatile( \
1850 "mr 11,%1\n\t" \
1851 "std 2,-16(11)\n\t" /* save tocptr */ \
1852 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1853 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1854 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1855 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1856 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1857 "ld 11, 0(11)\n\t" /* target->r11 */ \
1858 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1859 "mr 11,%1\n\t" \
1860 "mr %0,3\n\t" \
1861 "ld 2,-16(11)" /* restore tocptr */ \
1862 : /*out*/ "=r" (_res) \
1863 : /*in*/ "r" (&_argvec[2]) \
1864 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1865 ); \
1866 lval = (__typeof__(lval)) _res; \
1867 } while (0)
1868
1869#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1870 do { \
1871 volatile OrigFn _orig = (orig); \
1872 volatile unsigned long _argvec[3+5]; \
1873 volatile unsigned long _res; \
1874 /* _argvec[0] holds current r2 across the call */ \
1875 _argvec[1] = (unsigned long)_orig.r2; \
1876 _argvec[2] = (unsigned long)_orig.nraddr; \
1877 _argvec[2+1] = (unsigned long)arg1; \
1878 _argvec[2+2] = (unsigned long)arg2; \
1879 _argvec[2+3] = (unsigned long)arg3; \
1880 _argvec[2+4] = (unsigned long)arg4; \
1881 _argvec[2+5] = (unsigned long)arg5; \
1882 __asm__ volatile( \
1883 "mr 11,%1\n\t" \
1884 "std 2,-16(11)\n\t" /* save tocptr */ \
1885 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1886 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1887 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1888 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1889 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1890 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1891 "ld 11, 0(11)\n\t" /* target->r11 */ \
1892 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1893 "mr 11,%1\n\t" \
1894 "mr %0,3\n\t" \
1895 "ld 2,-16(11)" /* restore tocptr */ \
1896 : /*out*/ "=r" (_res) \
1897 : /*in*/ "r" (&_argvec[2]) \
1898 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1899 ); \
1900 lval = (__typeof__(lval)) _res; \
1901 } while (0)
1902
1903#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1904 do { \
1905 volatile OrigFn _orig = (orig); \
1906 volatile unsigned long _argvec[3+6]; \
1907 volatile unsigned long _res; \
1908 /* _argvec[0] holds current r2 across the call */ \
1909 _argvec[1] = (unsigned long)_orig.r2; \
1910 _argvec[2] = (unsigned long)_orig.nraddr; \
1911 _argvec[2+1] = (unsigned long)arg1; \
1912 _argvec[2+2] = (unsigned long)arg2; \
1913 _argvec[2+3] = (unsigned long)arg3; \
1914 _argvec[2+4] = (unsigned long)arg4; \
1915 _argvec[2+5] = (unsigned long)arg5; \
1916 _argvec[2+6] = (unsigned long)arg6; \
1917 __asm__ volatile( \
1918 "mr 11,%1\n\t" \
1919 "std 2,-16(11)\n\t" /* save tocptr */ \
1920 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1921 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1922 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1923 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1924 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1925 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1926 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
1927 "ld 11, 0(11)\n\t" /* target->r11 */ \
1928 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1929 "mr 11,%1\n\t" \
1930 "mr %0,3\n\t" \
1931 "ld 2,-16(11)" /* restore tocptr */ \
1932 : /*out*/ "=r" (_res) \
1933 : /*in*/ "r" (&_argvec[2]) \
1934 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1935 ); \
1936 lval = (__typeof__(lval)) _res; \
1937 } while (0)
1938
1939#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1940 arg7) \
1941 do { \
1942 volatile OrigFn _orig = (orig); \
1943 volatile unsigned long _argvec[3+7]; \
1944 volatile unsigned long _res; \
1945 /* _argvec[0] holds current r2 across the call */ \
1946 _argvec[1] = (unsigned long)_orig.r2; \
1947 _argvec[2] = (unsigned long)_orig.nraddr; \
1948 _argvec[2+1] = (unsigned long)arg1; \
1949 _argvec[2+2] = (unsigned long)arg2; \
1950 _argvec[2+3] = (unsigned long)arg3; \
1951 _argvec[2+4] = (unsigned long)arg4; \
1952 _argvec[2+5] = (unsigned long)arg5; \
1953 _argvec[2+6] = (unsigned long)arg6; \
1954 _argvec[2+7] = (unsigned long)arg7; \
1955 __asm__ volatile( \
1956 "mr 11,%1\n\t" \
1957 "std 2,-16(11)\n\t" /* save tocptr */ \
1958 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1959 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1960 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1961 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1962 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1963 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1964 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
1965 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
1966 "ld 11, 0(11)\n\t" /* target->r11 */ \
1967 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1968 "mr 11,%1\n\t" \
1969 "mr %0,3\n\t" \
1970 "ld 2,-16(11)" /* restore tocptr */ \
1971 : /*out*/ "=r" (_res) \
1972 : /*in*/ "r" (&_argvec[2]) \
1973 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1974 ); \
1975 lval = (__typeof__(lval)) _res; \
1976 } while (0)
1977
1978#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1979 arg7,arg8) \
1980 do { \
1981 volatile OrigFn _orig = (orig); \
1982 volatile unsigned long _argvec[3+8]; \
1983 volatile unsigned long _res; \
1984 /* _argvec[0] holds current r2 across the call */ \
1985 _argvec[1] = (unsigned long)_orig.r2; \
1986 _argvec[2] = (unsigned long)_orig.nraddr; \
1987 _argvec[2+1] = (unsigned long)arg1; \
1988 _argvec[2+2] = (unsigned long)arg2; \
1989 _argvec[2+3] = (unsigned long)arg3; \
1990 _argvec[2+4] = (unsigned long)arg4; \
1991 _argvec[2+5] = (unsigned long)arg5; \
1992 _argvec[2+6] = (unsigned long)arg6; \
1993 _argvec[2+7] = (unsigned long)arg7; \
1994 _argvec[2+8] = (unsigned long)arg8; \
1995 __asm__ volatile( \
1996 "mr 11,%1\n\t" \
1997 "std 2,-16(11)\n\t" /* save tocptr */ \
1998 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1999 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2000 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2001 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2002 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2003 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2004 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2005 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2006 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2007 "ld 11, 0(11)\n\t" /* target->r11 */ \
2008 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2009 "mr 11,%1\n\t" \
2010 "mr %0,3\n\t" \
2011 "ld 2,-16(11)" /* restore tocptr */ \
2012 : /*out*/ "=r" (_res) \
2013 : /*in*/ "r" (&_argvec[2]) \
2014 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2015 ); \
2016 lval = (__typeof__(lval)) _res; \
2017 } while (0)
2018
2019#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2020 arg7,arg8,arg9) \
2021 do { \
2022 volatile OrigFn _orig = (orig); \
2023 volatile unsigned long _argvec[3+9]; \
2024 volatile unsigned long _res; \
2025 /* _argvec[0] holds current r2 across the call */ \
2026 _argvec[1] = (unsigned long)_orig.r2; \
2027 _argvec[2] = (unsigned long)_orig.nraddr; \
2028 _argvec[2+1] = (unsigned long)arg1; \
2029 _argvec[2+2] = (unsigned long)arg2; \
2030 _argvec[2+3] = (unsigned long)arg3; \
2031 _argvec[2+4] = (unsigned long)arg4; \
2032 _argvec[2+5] = (unsigned long)arg5; \
2033 _argvec[2+6] = (unsigned long)arg6; \
2034 _argvec[2+7] = (unsigned long)arg7; \
2035 _argvec[2+8] = (unsigned long)arg8; \
2036 _argvec[2+9] = (unsigned long)arg9; \
2037 __asm__ volatile( \
2038 "mr 11,%1\n\t" \
2039 "std 2,-16(11)\n\t" /* save tocptr */ \
2040 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2041 "addi 1,1,-128\n\t" /* expand stack frame */ \
2042 /* arg9 */ \
2043 "ld 3,72(11)\n\t" \
2044 "std 3,112(1)\n\t" \
2045 /* args1-8 */ \
2046 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2047 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2048 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2049 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2050 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2051 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2052 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2053 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2054 "ld 11, 0(11)\n\t" /* target->r11 */ \
2055 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2056 "mr 11,%1\n\t" \
2057 "mr %0,3\n\t" \
2058 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2059 "addi 1,1,128" /* restore frame */ \
2060 : /*out*/ "=r" (_res) \
2061 : /*in*/ "r" (&_argvec[2]) \
2062 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2063 ); \
2064 lval = (__typeof__(lval)) _res; \
2065 } while (0)
2066
2067#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2068 arg7,arg8,arg9,arg10) \
2069 do { \
2070 volatile OrigFn _orig = (orig); \
2071 volatile unsigned long _argvec[3+10]; \
2072 volatile unsigned long _res; \
2073 /* _argvec[0] holds current r2 across the call */ \
2074 _argvec[1] = (unsigned long)_orig.r2; \
2075 _argvec[2] = (unsigned long)_orig.nraddr; \
2076 _argvec[2+1] = (unsigned long)arg1; \
2077 _argvec[2+2] = (unsigned long)arg2; \
2078 _argvec[2+3] = (unsigned long)arg3; \
2079 _argvec[2+4] = (unsigned long)arg4; \
2080 _argvec[2+5] = (unsigned long)arg5; \
2081 _argvec[2+6] = (unsigned long)arg6; \
2082 _argvec[2+7] = (unsigned long)arg7; \
2083 _argvec[2+8] = (unsigned long)arg8; \
2084 _argvec[2+9] = (unsigned long)arg9; \
2085 _argvec[2+10] = (unsigned long)arg10; \
2086 __asm__ volatile( \
2087 "mr 11,%1\n\t" \
2088 "std 2,-16(11)\n\t" /* save tocptr */ \
2089 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2090 "addi 1,1,-128\n\t" /* expand stack frame */ \
2091 /* arg10 */ \
2092 "ld 3,80(11)\n\t" \
2093 "std 3,120(1)\n\t" \
2094 /* arg9 */ \
2095 "ld 3,72(11)\n\t" \
2096 "std 3,112(1)\n\t" \
2097 /* args1-8 */ \
2098 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2099 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2100 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2101 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2102 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2103 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2104 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2105 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2106 "ld 11, 0(11)\n\t" /* target->r11 */ \
2107 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2108 "mr 11,%1\n\t" \
2109 "mr %0,3\n\t" \
2110 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2111 "addi 1,1,128" /* restore frame */ \
2112 : /*out*/ "=r" (_res) \
2113 : /*in*/ "r" (&_argvec[2]) \
2114 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2115 ); \
2116 lval = (__typeof__(lval)) _res; \
2117 } while (0)
2118
2119#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2120 arg7,arg8,arg9,arg10,arg11) \
2121 do { \
2122 volatile OrigFn _orig = (orig); \
2123 volatile unsigned long _argvec[3+11]; \
2124 volatile unsigned long _res; \
2125 /* _argvec[0] holds current r2 across the call */ \
2126 _argvec[1] = (unsigned long)_orig.r2; \
2127 _argvec[2] = (unsigned long)_orig.nraddr; \
2128 _argvec[2+1] = (unsigned long)arg1; \
2129 _argvec[2+2] = (unsigned long)arg2; \
2130 _argvec[2+3] = (unsigned long)arg3; \
2131 _argvec[2+4] = (unsigned long)arg4; \
2132 _argvec[2+5] = (unsigned long)arg5; \
2133 _argvec[2+6] = (unsigned long)arg6; \
2134 _argvec[2+7] = (unsigned long)arg7; \
2135 _argvec[2+8] = (unsigned long)arg8; \
2136 _argvec[2+9] = (unsigned long)arg9; \
2137 _argvec[2+10] = (unsigned long)arg10; \
2138 _argvec[2+11] = (unsigned long)arg11; \
2139 __asm__ volatile( \
2140 "mr 11,%1\n\t" \
2141 "std 2,-16(11)\n\t" /* save tocptr */ \
2142 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2143 "addi 1,1,-144\n\t" /* expand stack frame */ \
2144 /* arg11 */ \
2145 "ld 3,88(11)\n\t" \
2146 "std 3,128(1)\n\t" \
2147 /* arg10 */ \
2148 "ld 3,80(11)\n\t" \
2149 "std 3,120(1)\n\t" \
2150 /* arg9 */ \
2151 "ld 3,72(11)\n\t" \
2152 "std 3,112(1)\n\t" \
2153 /* args1-8 */ \
2154 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2155 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2156 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2157 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2158 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2159 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2160 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2161 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2162 "ld 11, 0(11)\n\t" /* target->r11 */ \
2163 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2164 "mr 11,%1\n\t" \
2165 "mr %0,3\n\t" \
2166 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2167 "addi 1,1,144" /* restore frame */ \
2168 : /*out*/ "=r" (_res) \
2169 : /*in*/ "r" (&_argvec[2]) \
2170 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2171 ); \
2172 lval = (__typeof__(lval)) _res; \
2173 } while (0)
2174
2175#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2176 arg7,arg8,arg9,arg10,arg11,arg12) \
2177 do { \
2178 volatile OrigFn _orig = (orig); \
2179 volatile unsigned long _argvec[3+12]; \
2180 volatile unsigned long _res; \
2181 /* _argvec[0] holds current r2 across the call */ \
2182 _argvec[1] = (unsigned long)_orig.r2; \
2183 _argvec[2] = (unsigned long)_orig.nraddr; \
2184 _argvec[2+1] = (unsigned long)arg1; \
2185 _argvec[2+2] = (unsigned long)arg2; \
2186 _argvec[2+3] = (unsigned long)arg3; \
2187 _argvec[2+4] = (unsigned long)arg4; \
2188 _argvec[2+5] = (unsigned long)arg5; \
2189 _argvec[2+6] = (unsigned long)arg6; \
2190 _argvec[2+7] = (unsigned long)arg7; \
2191 _argvec[2+8] = (unsigned long)arg8; \
2192 _argvec[2+9] = (unsigned long)arg9; \
2193 _argvec[2+10] = (unsigned long)arg10; \
2194 _argvec[2+11] = (unsigned long)arg11; \
2195 _argvec[2+12] = (unsigned long)arg12; \
2196 __asm__ volatile( \
2197 "mr 11,%1\n\t" \
2198 "std 2,-16(11)\n\t" /* save tocptr */ \
2199 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2200 "addi 1,1,-144\n\t" /* expand stack frame */ \
2201 /* arg12 */ \
2202 "ld 3,96(11)\n\t" \
2203 "std 3,136(1)\n\t" \
2204 /* arg11 */ \
2205 "ld 3,88(11)\n\t" \
2206 "std 3,128(1)\n\t" \
2207 /* arg10 */ \
2208 "ld 3,80(11)\n\t" \
2209 "std 3,120(1)\n\t" \
2210 /* arg9 */ \
2211 "ld 3,72(11)\n\t" \
2212 "std 3,112(1)\n\t" \
2213 /* args1-8 */ \
2214 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2215 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2216 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2217 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2218 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2219 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2220 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2221 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2222 "ld 11, 0(11)\n\t" /* target->r11 */ \
2223 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2224 "mr 11,%1\n\t" \
2225 "mr %0,3\n\t" \
2226 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2227 "addi 1,1,144" /* restore frame */ \
2228 : /*out*/ "=r" (_res) \
2229 : /*in*/ "r" (&_argvec[2]) \
2230 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2231 ); \
2232 lval = (__typeof__(lval)) _res; \
2233 } while (0)
2234
sewardj9734b202006-01-17 01:49:37 +00002235#endif /* ARCH_ppc64 */
2236
sewardj0ec07f32006-01-12 12:32:32 +00002237
2238/* ------------------------------------------------------------------ */
2239/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
2240/* */
njn30d76c62005-06-18 15:07:39 +00002241/* ------------------------------------------------------------------ */
2242
sewardj2e93c502002-04-12 11:12:52 +00002243/* Some request codes. There are many more of these, but most are not
2244 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00002245 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00002246
sewardj0ec07f32006-01-12 12:32:32 +00002247 Core ones are in the range 0x00000000--0x0000ffff. The non-public
2248 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00002249*/
2250
sewardj0ec07f32006-01-12 12:32:32 +00002251/* These macros are used by tools -- they must be public, but don't
2252 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00002253#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00002254 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00002255#define VG_IS_TOOL_USERREQ(a, b, v) \
2256 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00002257
sewardj5ce4b152006-03-11 12:57:41 +00002258/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
2259 This enum comprises an ABI exported by Valgrind to programs
2260 which use client requests. DO NOT CHANGE THE ORDER OF THESE
2261 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00002262typedef
njn4c791212003-05-02 17:53:54 +00002263 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
2264 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00002265
sewardj0ec07f32006-01-12 12:32:32 +00002266 /* These allow any function to be called from the simulated
2267 CPU but run on the real CPU. Nb: the first arg passed to
2268 the function is always the ThreadId of the running
2269 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00002270 function, etc. */
njn4c791212003-05-02 17:53:54 +00002271 VG_USERREQ__CLIENT_CALL0 = 0x1101,
2272 VG_USERREQ__CLIENT_CALL1 = 0x1102,
2273 VG_USERREQ__CLIENT_CALL2 = 0x1103,
2274 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00002275
sewardj0ec07f32006-01-12 12:32:32 +00002276 /* Can be useful in regression testing suites -- eg. can
2277 send Valgrind's output to /dev/null and still count
2278 errors. */
njn4c791212003-05-02 17:53:54 +00002279 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00002280
sewardj0ec07f32006-01-12 12:32:32 +00002281 /* These are useful and can be interpreted by any tool that
2282 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00002283 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
2284 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00002285 /* Memory pool support. */
2286 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
2287 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
2288 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
2289 VG_USERREQ__MEMPOOL_FREE = 0x1306,
njnd7994182003-10-02 13:44:04 +00002290
fitzhardinge39de4b42003-10-31 07:12:21 +00002291 /* Allow printfs to valgrind log. */
njn30d76c62005-06-18 15:07:39 +00002292 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00002293 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
2294
2295 /* Stack support. */
2296 VG_USERREQ__STACK_REGISTER = 0x1501,
2297 VG_USERREQ__STACK_DEREGISTER = 0x1502,
2298 VG_USERREQ__STACK_CHANGE = 0x1503,
njn25e49d8e72002-09-23 09:36:25 +00002299 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00002300
sewardj0ec07f32006-01-12 12:32:32 +00002301#if !defined(__GNUC__)
2302# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00002303#endif
sewardj2e93c502002-04-12 11:12:52 +00002304
sewardj0ec07f32006-01-12 12:32:32 +00002305/* Returns the number of Valgrinds this code is running under. That
2306 is, 0 if running natively, 1 if running under Valgrind, 2 if
2307 running under Valgrind which is running under another Valgrind,
2308 etc. */
2309#define RUNNING_ON_VALGRIND __extension__ \
2310 ({unsigned int _qzz_res; \
2311 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \
2312 VG_USERREQ__RUNNING_ON_VALGRIND, \
sewardj9af10a12006-02-01 14:59:42 +00002313 0, 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00002314 _qzz_res; \
sewardjde4a1d02002-03-22 01:27:54 +00002315 })
2316
2317
sewardj18d75132002-05-16 11:06:21 +00002318/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
2319 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
2320 since it provides a way to make sure valgrind will retranslate the
2321 invalidated area. Returns no value. */
sewardj0ec07f32006-01-12 12:32:32 +00002322#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
2323 {unsigned int _qzz_res; \
2324 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2325 VG_USERREQ__DISCARD_TRANSLATIONS, \
sewardj9af10a12006-02-01 14:59:42 +00002326 _qzz_addr, _qzz_len, 0, 0, 0); \
sewardj18d75132002-05-16 11:06:21 +00002327 }
2328
njn26aba4d2005-05-16 13:31:23 +00002329
sewardj0ec07f32006-01-12 12:32:32 +00002330/* These requests are for getting Valgrind itself to print something.
2331 Possibly with a backtrace. This is a really ugly hack. */
2332
2333#if defined(NVALGRIND)
2334
2335# define VALGRIND_PRINTF(...)
2336# define VALGRIND_PRINTF_BACKTRACE(...)
njn26aba4d2005-05-16 13:31:23 +00002337
2338#else /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00002339
fitzhardingea09a1b52003-11-07 23:09:48 +00002340int VALGRIND_PRINTF(const char *format, ...)
2341 __attribute__((format(__printf__, 1, 2)));
fitzhardinge39de4b42003-10-31 07:12:21 +00002342__attribute__((weak))
2343int
fitzhardingea09a1b52003-11-07 23:09:48 +00002344VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00002345{
njnc6168192004-11-29 13:54:10 +00002346 unsigned long _qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00002347 va_list vargs;
2348 va_start(vargs, format);
sewardj0ec07f32006-01-12 12:32:32 +00002349 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF,
sewardj9af10a12006-02-01 14:59:42 +00002350 (unsigned long)format, (unsigned long)vargs,
2351 0, 0, 0);
fitzhardinge39de4b42003-10-31 07:12:21 +00002352 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00002353 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00002354}
2355
fitzhardingea09a1b52003-11-07 23:09:48 +00002356int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
2357 __attribute__((format(__printf__, 1, 2)));
fitzhardinge39de4b42003-10-31 07:12:21 +00002358__attribute__((weak))
2359int
fitzhardingea09a1b52003-11-07 23:09:48 +00002360VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00002361{
njnc6168192004-11-29 13:54:10 +00002362 unsigned long _qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00002363 va_list vargs;
2364 va_start(vargs, format);
sewardj0ec07f32006-01-12 12:32:32 +00002365 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE,
sewardj9af10a12006-02-01 14:59:42 +00002366 (unsigned long)format, (unsigned long)vargs,
2367 0, 0, 0);
fitzhardinge39de4b42003-10-31 07:12:21 +00002368 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00002369 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00002370}
2371
fitzhardinge39de4b42003-10-31 07:12:21 +00002372#endif /* NVALGRIND */
sewardj18d75132002-05-16 11:06:21 +00002373
sewardj0ec07f32006-01-12 12:32:32 +00002374
njn3e884182003-04-15 13:03:23 +00002375/* These requests allow control to move from the simulated CPU to the
2376 real CPU, calling an arbitary function */
sewardj0ec07f32006-01-12 12:32:32 +00002377#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
2378 ({unsigned long _qyy_res; \
2379 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
2380 VG_USERREQ__CLIENT_CALL0, \
2381 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00002382 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00002383 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00002384 })
2385
sewardj0ec07f32006-01-12 12:32:32 +00002386#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
2387 ({unsigned long _qyy_res; \
2388 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
2389 VG_USERREQ__CLIENT_CALL1, \
2390 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00002391 _qyy_arg1, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00002392 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00002393 })
2394
sewardj0ec07f32006-01-12 12:32:32 +00002395#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
2396 ({unsigned long _qyy_res; \
2397 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
2398 VG_USERREQ__CLIENT_CALL2, \
2399 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00002400 _qyy_arg1, _qyy_arg2, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00002401 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00002402 })
2403
sewardj0ec07f32006-01-12 12:32:32 +00002404#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
2405 ({unsigned long _qyy_res; \
2406 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
2407 VG_USERREQ__CLIENT_CALL3, \
2408 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00002409 _qyy_arg1, _qyy_arg2, \
2410 _qyy_arg3, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00002411 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00002412 })
2413
2414
nethercote7cc9c232004-01-21 15:08:04 +00002415/* Counts the number of errors that have been recorded by a tool. Nb:
2416 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00002417 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00002418#define VALGRIND_COUNT_ERRORS \
2419 ({unsigned int _qyy_res; \
2420 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
2421 VG_USERREQ__COUNT_ERRORS, \
sewardj9af10a12006-02-01 14:59:42 +00002422 0, 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00002423 _qyy_res; \
njn47363ab2003-04-21 13:24:40 +00002424 })
2425
njnd7994182003-10-02 13:44:04 +00002426/* Mark a block of memory as having been allocated by a malloc()-like
2427 function. `addr' is the start of the usable block (ie. after any
2428 redzone) `rzB' is redzone size if the allocator can apply redzones;
2429 use '0' if not. Adding redzones makes it more likely Valgrind will spot
2430 block overruns. `is_zeroed' indicates if the memory is zeroed, as it is
2431 for calloc(). Put it immediately after the point where a block is
2432 allocated.
2433
2434 If you're allocating memory via superblocks, and then handing out small
2435 chunks of each superblock, if you don't have redzones on your small
2436 blocks, it's worth marking the superblock with VALGRIND_MAKE_NOACCESS
2437 when it's created, so that block overruns are detected. But if you can
2438 put redzones on, it's probably better to not do this, so that messages
2439 for small overruns are described in terms of the small block rather than
2440 the superblock (but if you have a big overrun that skips over a redzone,
2441 you could miss an error this way). See memcheck/tests/custom_alloc.c
2442 for an example.
2443
2444 Nb: block must be freed via a free()-like function specified
2445 with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */
sewardj0ec07f32006-01-12 12:32:32 +00002446#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
2447 {unsigned int _qzz_res; \
2448 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2449 VG_USERREQ__MALLOCLIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00002450 addr, sizeB, rzB, is_zeroed, 0); \
njnd7994182003-10-02 13:44:04 +00002451 }
2452
2453/* Mark a block of memory as having been freed by a free()-like function.
2454 `rzB' is redzone size; it must match that given to
2455 VALGRIND_MALLOCLIKE_BLOCK. Memory not freed will be detected by the leak
2456 checker. Put it immediately after the point where the block is freed. */
sewardj0ec07f32006-01-12 12:32:32 +00002457#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
2458 {unsigned int _qzz_res; \
2459 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2460 VG_USERREQ__FREELIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00002461 addr, rzB, 0, 0, 0); \
njnd7994182003-10-02 13:44:04 +00002462 }
2463
rjwalshbc0bb832004-06-19 18:12:36 +00002464/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00002465#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
2466 {unsigned int _qzz_res; \
2467 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2468 VG_USERREQ__CREATE_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00002469 pool, rzB, is_zeroed, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00002470 }
2471
2472/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00002473#define VALGRIND_DESTROY_MEMPOOL(pool) \
2474 {unsigned int _qzz_res; \
2475 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2476 VG_USERREQ__DESTROY_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00002477 pool, 0, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00002478 }
2479
2480/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00002481#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
2482 {unsigned int _qzz_res; \
2483 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2484 VG_USERREQ__MEMPOOL_ALLOC, \
sewardj9af10a12006-02-01 14:59:42 +00002485 pool, addr, size, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00002486 }
2487
2488/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00002489#define VALGRIND_MEMPOOL_FREE(pool, addr) \
2490 {unsigned int _qzz_res; \
2491 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2492 VG_USERREQ__MEMPOOL_FREE, \
sewardj9af10a12006-02-01 14:59:42 +00002493 pool, addr, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00002494 }
2495
rjwalsh0140af52005-06-04 20:42:33 +00002496/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00002497#define VALGRIND_STACK_REGISTER(start, end) \
2498 ({unsigned int _qzz_res; \
2499 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2500 VG_USERREQ__STACK_REGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00002501 start, end, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00002502 _qzz_res; \
rjwalsh0140af52005-06-04 20:42:33 +00002503 })
2504
2505/* Unmark the piece of memory associated with a stack id as being a
2506 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00002507#define VALGRIND_STACK_DEREGISTER(id) \
2508 {unsigned int _qzz_res; \
2509 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2510 VG_USERREQ__STACK_DEREGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00002511 id, 0, 0, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00002512 }
2513
2514/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00002515#define VALGRIND_STACK_CHANGE(id, start, end) \
2516 {unsigned int _qzz_res; \
2517 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
2518 VG_USERREQ__STACK_CHANGE, \
sewardj9af10a12006-02-01 14:59:42 +00002519 id, start, end, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00002520 }
2521
sewardj0ec07f32006-01-12 12:32:32 +00002522
2523#undef ARCH_x86
2524#undef ARCH_amd64
2525#undef ARCH_ppc32
2526#undef ARCH_ppc64
2527
njn3e884182003-04-15 13:03:23 +00002528#endif /* __VALGRIND_H */