blob: 1fa63acfad7c4b71d4c45352689b7a79fd08d099 [file] [log] [blame]
sewardjb5f6f512005-03-10 23:59:00 +00001/* -*- c -*-
njn25e49d8e72002-09-23 09:36:25 +00002 ----------------------------------------------------------------
3
4 Notice that the following BSD-style license applies to this one
njn7fd15d62006-03-31 12:05:04 +00005 file (valgrind.h) only. The rest of Valgrind is licensed under the
6 terms of the GNU General Public License, version 2, unless
7 otherwise indicated. See the COPYING file in the source
8 distribution for details.
njn25e49d8e72002-09-23 09:36:25 +00009
10 ----------------------------------------------------------------
11
njnb9c427c2004-12-01 14:14:42 +000012 This file is part of Valgrind, a dynamic binary instrumentation
13 framework.
sewardjde4a1d02002-03-22 01:27:54 +000014
njn9f207462009-03-10 22:02:09 +000015 Copyright (C) 2000-2009 Julian Seward. All rights reserved.
sewardjde4a1d02002-03-22 01:27:54 +000016
njn25e49d8e72002-09-23 09:36:25 +000017 Redistribution and use in source and binary forms, with or without
18 modification, are permitted provided that the following conditions
19 are met:
sewardjde4a1d02002-03-22 01:27:54 +000020
njn25e49d8e72002-09-23 09:36:25 +000021 1. Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
sewardjde4a1d02002-03-22 01:27:54 +000023
njn25e49d8e72002-09-23 09:36:25 +000024 2. The origin of this software must not be misrepresented; you must
25 not claim that you wrote the original software. If you use this
26 software in a product, an acknowledgment in the product
27 documentation would be appreciated but is not required.
sewardjde4a1d02002-03-22 01:27:54 +000028
njn25e49d8e72002-09-23 09:36:25 +000029 3. Altered source versions must be plainly marked as such, and must
30 not be misrepresented as being the original software.
31
32 4. The name of the author may not be used to endorse or promote
33 products derived from this software without specific prior written
34 permission.
35
36 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
37 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
40 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
45 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47
48 ----------------------------------------------------------------
49
50 Notice that the above BSD-style license applies to this one file
51 (valgrind.h) only. The entire rest of Valgrind is licensed under
52 the terms of the GNU General Public License, version 2. See the
53 COPYING file in the source distribution for details.
54
55 ----------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +000056*/
57
58
njn30d76c62005-06-18 15:07:39 +000059/* This file is for inclusion into client (your!) code.
60
61 You can use these macros to manipulate and query Valgrind's
62 execution inside your own programs.
63
64 The resulting executables will still run without Valgrind, just a
65 little bit more slowly than they otherwise would, but otherwise
66 unchanged. When not running on valgrind, each client request
sewardj0ec07f32006-01-12 12:32:32 +000067 consumes very few (eg. 7) instructions, so the resulting performance
njn30d76c62005-06-18 15:07:39 +000068 loss is negligible unless you plan to execute client requests
69 millions of times per second. Nevertheless, if that is still a
70 problem, you can compile with the NVALGRIND symbol defined (gcc
71 -DNVALGRIND) so that client requests are not even compiled in. */
72
sewardjde4a1d02002-03-22 01:27:54 +000073#ifndef __VALGRIND_H
74#define __VALGRIND_H
75
fitzhardinge39de4b42003-10-31 07:12:21 +000076#include <stdarg.h>
77
njn3dd0a912005-06-28 19:44:10 +000078/* Nb: this file might be included in a file compiled with -ansi. So
79 we can't use C++ style "//" comments nor the "asm" keyword (instead
80 use "__asm__"). */
81
sewardjf5c1a7f2006-10-17 01:32:48 +000082/* Derive some tags indicating what the target platform is. Note
sewardj0ec07f32006-01-12 12:32:32 +000083 that in this file we're using the compiler's CPP symbols for
84 identifying architectures, which are different to the ones we use
85 within the rest of Valgrind. Note, __powerpc__ is active for both
86 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
sewardjf5c1a7f2006-10-17 01:32:48 +000087 latter (on Linux, that is). */
88#undef PLAT_x86_linux
89#undef PLAT_amd64_linux
90#undef PLAT_ppc32_linux
91#undef PLAT_ppc64_linux
92#undef PLAT_ppc32_aix5
93#undef PLAT_ppc64_aix5
sewardj0ec07f32006-01-12 12:32:32 +000094
sewardjf5c1a7f2006-10-17 01:32:48 +000095#if !defined(_AIX) && defined(__i386__)
96# define PLAT_x86_linux 1
97#elif !defined(_AIX) && defined(__x86_64__)
98# define PLAT_amd64_linux 1
99#elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__)
100# define PLAT_ppc32_linux 1
101#elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__)
102# define PLAT_ppc64_linux 1
103#elif defined(_AIX) && defined(__64BIT__)
104# define PLAT_ppc64_aix5 1
105#elif defined(_AIX) && !defined(__64BIT__)
106# define PLAT_ppc32_aix5 1
sewardjb5f6f512005-03-10 23:59:00 +0000107#endif
108
sewardjf5c1a7f2006-10-17 01:32:48 +0000109
110/* If we're not compiling for our target platform, don't generate
sewardj0ec07f32006-01-12 12:32:32 +0000111 any inline asms. */
sewardjf5c1a7f2006-10-17 01:32:48 +0000112#if !defined(PLAT_x86_linux) && !defined(PLAT_amd64_linux) \
113 && !defined(PLAT_ppc32_linux) && !defined(PLAT_ppc64_linux) \
114 && !defined(PLAT_ppc32_aix5) && !defined(PLAT_ppc64_aix5)
sewardj0ec07f32006-01-12 12:32:32 +0000115# if !defined(NVALGRIND)
116# define NVALGRIND 1
117# endif
118#endif
119
120
njn30d76c62005-06-18 15:07:39 +0000121/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000122/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
123/* in here of use to end-users -- skip to the next section. */
njn30d76c62005-06-18 15:07:39 +0000124/* ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000125
sewardj0ec07f32006-01-12 12:32:32 +0000126#if defined(NVALGRIND)
njn26aba4d2005-05-16 13:31:23 +0000127
128/* Define NVALGRIND to completely remove the Valgrind magic sequence
sewardj0ec07f32006-01-12 12:32:32 +0000129 from the compiled code (analogous to NDEBUG's effects on
130 assert()) */
131#define VALGRIND_DO_CLIENT_REQUEST( \
132 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000133 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000134 { \
135 (_zzq_rlval) = (_zzq_default); \
njn26aba4d2005-05-16 13:31:23 +0000136 }
137
sewardj0ec07f32006-01-12 12:32:32 +0000138#else /* ! NVALGRIND */
nethercotee90c6832004-10-18 18:07:49 +0000139
sewardj0ec07f32006-01-12 12:32:32 +0000140/* The following defines the magic code sequences which the JITter
141 spots and handles magically. Don't look too closely at them as
142 they will rot your brain.
143
144 The assembly code sequences for all architectures is in this one
145 file. This is because this file must be stand-alone, and we don't
146 want to have multiple files.
147
148 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
149 value gets put in the return slot, so that everything works when
150 this is executed not under Valgrind. Args are passed in a memory
151 block, and so there's no intrinsic limit to the number that could
sewardj9af10a12006-02-01 14:59:42 +0000152 be passed, but it's currently five.
nethercotee90c6832004-10-18 18:07:49 +0000153
nethercote54265442004-10-26 12:56:58 +0000154 The macro args are:
155 _zzq_rlval result lvalue
156 _zzq_default default value (result returned when running on real CPU)
157 _zzq_request request code
sewardj9af10a12006-02-01 14:59:42 +0000158 _zzq_arg1..5 request params
nethercote54265442004-10-26 12:56:58 +0000159
sewardj0ec07f32006-01-12 12:32:32 +0000160 The other two macros are used to support function wrapping, and are
sewardjd68ac3e2006-01-20 14:31:57 +0000161 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
162 guest's NRADDR pseudo-register and whatever other information is
163 needed to safely run the call original from the wrapper: on
164 ppc64-linux, the R2 value at the divert point is also needed. This
165 information is abstracted into a user-visible type, OrigFn.
166
167 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
168 guest, but guarantees that the branch instruction will not be
169 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
170 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
171 complete inline asm, since it needs to be combined with more magic
172 inline asm stuff to be useful.
nethercotee90c6832004-10-18 18:07:49 +0000173*/
174
sewardjf5c1a7f2006-10-17 01:32:48 +0000175/* ------------------------- x86-linux ------------------------- */
sewardjde4a4ab2005-03-23 13:10:32 +0000176
sewardjf5c1a7f2006-10-17 01:32:48 +0000177#if defined(PLAT_x86_linux)
sewardjc8858442006-01-20 15:17:20 +0000178
179typedef
180 struct {
181 unsigned int nraddr; /* where's the code? */
182 }
183 OrigFn;
184
sewardj0ec07f32006-01-12 12:32:32 +0000185#define __SPECIAL_INSTRUCTION_PREAMBLE \
186 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000187 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000188
sewardj0ec07f32006-01-12 12:32:32 +0000189#define VALGRIND_DO_CLIENT_REQUEST( \
190 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000191 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
192 { volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000193 volatile unsigned int _zzq_result; \
194 _zzq_args[0] = (unsigned int)(_zzq_request); \
195 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
196 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
197 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
198 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000199 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000200 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
201 /* %EDX = client_request ( %EAX ) */ \
202 "xchgl %%ebx,%%ebx" \
203 : "=d" (_zzq_result) \
204 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
205 : "cc", "memory" \
206 ); \
207 _zzq_rlval = _zzq_result; \
cerion85665ca2005-06-20 15:51:07 +0000208 }
sewardj2c48c7b2005-11-29 13:05:56 +0000209
sewardjc8858442006-01-20 15:17:20 +0000210#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
211 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
212 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000213 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
214 /* %EAX = guest_NRADDR */ \
215 "xchgl %%ecx,%%ecx" \
216 : "=a" (__addr) \
217 : \
218 : "cc", "memory" \
219 ); \
sewardjc8858442006-01-20 15:17:20 +0000220 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000221 }
sewardj0ec07f32006-01-12 12:32:32 +0000222
223#define VALGRIND_CALL_NOREDIR_EAX \
224 __SPECIAL_INSTRUCTION_PREAMBLE \
225 /* call-noredir *%EAX */ \
226 "xchgl %%edx,%%edx\n\t"
sewardjf5c1a7f2006-10-17 01:32:48 +0000227#endif /* PLAT_x86_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000228
sewardjf5c1a7f2006-10-17 01:32:48 +0000229/* ------------------------ amd64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000230
sewardjf5c1a7f2006-10-17 01:32:48 +0000231#if defined(PLAT_amd64_linux)
sewardjc8858442006-01-20 15:17:20 +0000232
233typedef
234 struct {
235 unsigned long long int nraddr; /* where's the code? */
236 }
237 OrigFn;
238
sewardj0ec07f32006-01-12 12:32:32 +0000239#define __SPECIAL_INSTRUCTION_PREAMBLE \
240 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000241 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000242
243#define VALGRIND_DO_CLIENT_REQUEST( \
244 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000245 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
246 { volatile unsigned long long int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000247 volatile unsigned long long int _zzq_result; \
248 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
249 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
250 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
251 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
252 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000253 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000254 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
255 /* %RDX = client_request ( %RAX ) */ \
256 "xchgq %%rbx,%%rbx" \
257 : "=d" (_zzq_result) \
258 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
259 : "cc", "memory" \
260 ); \
261 _zzq_rlval = _zzq_result; \
262 }
263
sewardjc8858442006-01-20 15:17:20 +0000264#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
265 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
266 volatile unsigned long long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000267 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
268 /* %RAX = guest_NRADDR */ \
269 "xchgq %%rcx,%%rcx" \
270 : "=a" (__addr) \
271 : \
272 : "cc", "memory" \
273 ); \
sewardjc8858442006-01-20 15:17:20 +0000274 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000275 }
276
277#define VALGRIND_CALL_NOREDIR_RAX \
278 __SPECIAL_INSTRUCTION_PREAMBLE \
279 /* call-noredir *%RAX */ \
280 "xchgq %%rdx,%%rdx\n\t"
sewardjf5c1a7f2006-10-17 01:32:48 +0000281#endif /* PLAT_amd64_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000282
sewardjf5c1a7f2006-10-17 01:32:48 +0000283/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000284
sewardjf5c1a7f2006-10-17 01:32:48 +0000285#if defined(PLAT_ppc32_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000286
287typedef
288 struct {
sewardjc8858442006-01-20 15:17:20 +0000289 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000290 }
291 OrigFn;
292
sewardj0ec07f32006-01-12 12:32:32 +0000293#define __SPECIAL_INSTRUCTION_PREAMBLE \
294 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000295 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000296
297#define VALGRIND_DO_CLIENT_REQUEST( \
298 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000299 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000300 \
sewardj9af10a12006-02-01 14:59:42 +0000301 { unsigned int _zzq_args[6]; \
sewardj1c5bcb12006-12-08 21:29:46 +0000302 unsigned int _zzq_result; \
303 unsigned int* _zzq_ptr; \
sewardj0ec07f32006-01-12 12:32:32 +0000304 _zzq_args[0] = (unsigned int)(_zzq_request); \
305 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
306 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
307 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
308 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000309 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000310 _zzq_ptr = _zzq_args; \
sewardj1c5bcb12006-12-08 21:29:46 +0000311 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
312 "mr 4,%2\n\t" /*ptr*/ \
313 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj0ec07f32006-01-12 12:32:32 +0000314 /* %R3 = client_request ( %R4 ) */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000315 "or 1,1,1\n\t" \
316 "mr %0,3" /*result*/ \
317 : "=b" (_zzq_result) \
318 : "b" (_zzq_default), "b" (_zzq_ptr) \
319 : "cc", "memory", "r3", "r4"); \
sewardj0ec07f32006-01-12 12:32:32 +0000320 _zzq_rlval = _zzq_result; \
321 }
322
sewardjd68ac3e2006-01-20 14:31:57 +0000323#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
324 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj1c5bcb12006-12-08 21:29:46 +0000325 unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000326 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
327 /* %R3 = guest_NRADDR */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000328 "or 2,2,2\n\t" \
329 "mr %0,3" \
330 : "=b" (__addr) \
sewardj0ec07f32006-01-12 12:32:32 +0000331 : \
sewardj1c5bcb12006-12-08 21:29:46 +0000332 : "cc", "memory", "r3" \
sewardj0ec07f32006-01-12 12:32:32 +0000333 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000334 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000335 }
336
337#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
338 __SPECIAL_INSTRUCTION_PREAMBLE \
339 /* branch-and-link-to-noredir *%R11 */ \
340 "or 3,3,3\n\t"
sewardjf5c1a7f2006-10-17 01:32:48 +0000341#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000342
sewardjf5c1a7f2006-10-17 01:32:48 +0000343/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000344
sewardjf5c1a7f2006-10-17 01:32:48 +0000345#if defined(PLAT_ppc64_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000346
347typedef
348 struct {
349 unsigned long long int nraddr; /* where's the code? */
350 unsigned long long int r2; /* what tocptr do we need? */
351 }
352 OrigFn;
353
sewardj1a85f4f2006-01-12 21:15:35 +0000354#define __SPECIAL_INSTRUCTION_PREAMBLE \
355 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
356 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
357
sewardj0ec07f32006-01-12 12:32:32 +0000358#define VALGRIND_DO_CLIENT_REQUEST( \
359 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000360 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000361 \
sewardj9af10a12006-02-01 14:59:42 +0000362 { unsigned long long int _zzq_args[6]; \
sewardj1a85f4f2006-01-12 21:15:35 +0000363 register unsigned long long int _zzq_result __asm__("r3"); \
364 register unsigned long long int* _zzq_ptr __asm__("r4"); \
365 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
366 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
367 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
368 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
369 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000370 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000371 _zzq_ptr = _zzq_args; \
sewardj1a85f4f2006-01-12 21:15:35 +0000372 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
373 /* %R3 = client_request ( %R4 ) */ \
374 "or 1,1,1" \
375 : "=r" (_zzq_result) \
sewardj0ec07f32006-01-12 12:32:32 +0000376 : "0" (_zzq_default), "r" (_zzq_ptr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000377 : "cc", "memory"); \
378 _zzq_rlval = _zzq_result; \
sewardj0ec07f32006-01-12 12:32:32 +0000379 }
sewardj1a85f4f2006-01-12 21:15:35 +0000380
sewardjd68ac3e2006-01-20 14:31:57 +0000381#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
382 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
383 register unsigned long long int __addr __asm__("r3"); \
sewardj1a85f4f2006-01-12 21:15:35 +0000384 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
385 /* %R3 = guest_NRADDR */ \
386 "or 2,2,2" \
387 : "=r" (__addr) \
388 : \
389 : "cc", "memory" \
390 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000391 _zzq_orig->nraddr = __addr; \
392 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
393 /* %R3 = guest_NRADDR_GPR2 */ \
394 "or 4,4,4" \
395 : "=r" (__addr) \
396 : \
397 : "cc", "memory" \
398 ); \
399 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000400 }
401
402#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
403 __SPECIAL_INSTRUCTION_PREAMBLE \
404 /* branch-and-link-to-noredir *%R11 */ \
405 "or 3,3,3\n\t"
406
sewardjf5c1a7f2006-10-17 01:32:48 +0000407#endif /* PLAT_ppc64_linux */
cerion85665ca2005-06-20 15:51:07 +0000408
sewardjf5c1a7f2006-10-17 01:32:48 +0000409/* ------------------------ ppc32-aix5 ------------------------- */
410
411#if defined(PLAT_ppc32_aix5)
412
413typedef
414 struct {
415 unsigned int nraddr; /* where's the code? */
416 unsigned int r2; /* what tocptr do we need? */
417 }
418 OrigFn;
419
420#define __SPECIAL_INSTRUCTION_PREAMBLE \
421 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
422 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
423
424#define VALGRIND_DO_CLIENT_REQUEST( \
425 _zzq_rlval, _zzq_default, _zzq_request, \
426 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
427 \
428 { unsigned int _zzq_args[7]; \
429 register unsigned int _zzq_result; \
430 register unsigned int* _zzq_ptr; \
431 _zzq_args[0] = (unsigned int)(_zzq_request); \
432 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
433 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
434 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
435 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
436 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
437 _zzq_args[6] = (unsigned int)(_zzq_default); \
438 _zzq_ptr = _zzq_args; \
439 __asm__ volatile("mr 4,%1\n\t" \
440 "lwz 3, 24(4)\n\t" \
441 __SPECIAL_INSTRUCTION_PREAMBLE \
442 /* %R3 = client_request ( %R4 ) */ \
443 "or 1,1,1\n\t" \
444 "mr %0,3" \
445 : "=b" (_zzq_result) \
446 : "b" (_zzq_ptr) \
447 : "r3", "r4", "cc", "memory"); \
448 _zzq_rlval = _zzq_result; \
449 }
450
451#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
452 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
453 register unsigned int __addr; \
454 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
455 /* %R3 = guest_NRADDR */ \
456 "or 2,2,2\n\t" \
457 "mr %0,3" \
458 : "=b" (__addr) \
459 : \
460 : "r3", "cc", "memory" \
461 ); \
462 _zzq_orig->nraddr = __addr; \
463 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
464 /* %R3 = guest_NRADDR_GPR2 */ \
465 "or 4,4,4\n\t" \
466 "mr %0,3" \
467 : "=b" (__addr) \
468 : \
469 : "r3", "cc", "memory" \
470 ); \
471 _zzq_orig->r2 = __addr; \
472 }
473
474#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
475 __SPECIAL_INSTRUCTION_PREAMBLE \
476 /* branch-and-link-to-noredir *%R11 */ \
477 "or 3,3,3\n\t"
478
479#endif /* PLAT_ppc32_aix5 */
480
481/* ------------------------ ppc64-aix5 ------------------------- */
482
483#if defined(PLAT_ppc64_aix5)
484
485typedef
486 struct {
487 unsigned long long int nraddr; /* where's the code? */
488 unsigned long long int r2; /* what tocptr do we need? */
489 }
490 OrigFn;
491
492#define __SPECIAL_INSTRUCTION_PREAMBLE \
493 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
494 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
495
496#define VALGRIND_DO_CLIENT_REQUEST( \
497 _zzq_rlval, _zzq_default, _zzq_request, \
498 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
499 \
500 { unsigned long long int _zzq_args[7]; \
501 register unsigned long long int _zzq_result; \
502 register unsigned long long int* _zzq_ptr; \
503 _zzq_args[0] = (unsigned int long long)(_zzq_request); \
504 _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
505 _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
506 _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
507 _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
508 _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
509 _zzq_args[6] = (unsigned int long long)(_zzq_default); \
510 _zzq_ptr = _zzq_args; \
511 __asm__ volatile("mr 4,%1\n\t" \
512 "ld 3, 48(4)\n\t" \
513 __SPECIAL_INSTRUCTION_PREAMBLE \
514 /* %R3 = client_request ( %R4 ) */ \
515 "or 1,1,1\n\t" \
516 "mr %0,3" \
517 : "=b" (_zzq_result) \
518 : "b" (_zzq_ptr) \
519 : "r3", "r4", "cc", "memory"); \
520 _zzq_rlval = _zzq_result; \
521 }
522
523#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
524 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
525 register unsigned long long int __addr; \
526 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
527 /* %R3 = guest_NRADDR */ \
528 "or 2,2,2\n\t" \
529 "mr %0,3" \
530 : "=b" (__addr) \
531 : \
532 : "r3", "cc", "memory" \
533 ); \
534 _zzq_orig->nraddr = __addr; \
535 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
536 /* %R3 = guest_NRADDR_GPR2 */ \
537 "or 4,4,4\n\t" \
538 "mr %0,3" \
539 : "=b" (__addr) \
540 : \
541 : "r3", "cc", "memory" \
542 ); \
543 _zzq_orig->r2 = __addr; \
544 }
545
546#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
547 __SPECIAL_INSTRUCTION_PREAMBLE \
548 /* branch-and-link-to-noredir *%R11 */ \
549 "or 3,3,3\n\t"
550
551#endif /* PLAT_ppc64_aix5 */
552
553/* Insert assembly code for other platforms here... */
njn26aba4d2005-05-16 13:31:23 +0000554
sewardj37091fb2002-11-16 11:06:50 +0000555#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +0000556
nethercote69d9c462004-10-26 13:00:12 +0000557
njn30d76c62005-06-18 15:07:39 +0000558/* ------------------------------------------------------------------ */
sewardjf5c1a7f2006-10-17 01:32:48 +0000559/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
sewardj0ec07f32006-01-12 12:32:32 +0000560/* ugly. It's the least-worst tradeoff I can think of. */
561/* ------------------------------------------------------------------ */
562
563/* This section defines magic (a.k.a appalling-hack) macros for doing
564 guaranteed-no-redirection macros, so as to get from function
565 wrappers to the functions they are wrapping. The whole point is to
566 construct standard call sequences, but to do the call itself with a
567 special no-redirect call pseudo-instruction that the JIT
568 understands and handles specially. This section is long and
569 repetitious, and I can't see a way to make it shorter.
570
571 The naming scheme is as follows:
572
573 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
574
575 'W' stands for "word" and 'v' for "void". Hence there are
576 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
577 and for each, the possibility of returning a word-typed result, or
578 no result.
579*/
580
581/* Use these to write the name of your wrapper. NOTE: duplicates
582 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
583
njn5f5ef2a2009-05-11 08:01:09 +0000584/* Use an extra level of macroisation so as to ensure the soname/fnname
585 args are fully macro-expanded before pasting them together. */
586#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
587
sewardj0ec07f32006-01-12 12:32:32 +0000588#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
njn5f5ef2a2009-05-11 08:01:09 +0000589 VG_CONCAT4(_vgwZU_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000590
591#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
njn5f5ef2a2009-05-11 08:01:09 +0000592 VG_CONCAT4(_vgwZZ_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000593
sewardjd68ac3e2006-01-20 14:31:57 +0000594/* Use this macro from within a wrapper function to collect the
595 context (address and possibly other info) of the original function.
596 Once you have that you can then use it in one of the CALL_FN_
597 macros. The type of the argument _lval is OrigFn. */
598#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +0000599
600/* Derivatives of the main macros below, for calling functions
601 returning void. */
602
603#define CALL_FN_v_v(fnptr) \
604 do { volatile unsigned long _junk; \
605 CALL_FN_W_v(_junk,fnptr); } while (0)
606
607#define CALL_FN_v_W(fnptr, arg1) \
608 do { volatile unsigned long _junk; \
609 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
610
611#define CALL_FN_v_WW(fnptr, arg1,arg2) \
612 do { volatile unsigned long _junk; \
613 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
614
sewardj5ce4b152006-03-11 12:57:41 +0000615#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
616 do { volatile unsigned long _junk; \
617 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
618
sewardjf5c1a7f2006-10-17 01:32:48 +0000619/* ------------------------- x86-linux ------------------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000620
sewardjf5c1a7f2006-10-17 01:32:48 +0000621#if defined(PLAT_x86_linux)
sewardj0ec07f32006-01-12 12:32:32 +0000622
623/* These regs are trashed by the hidden call. No need to mention eax
624 as gcc can already see that, plus causes gcc to bomb. */
625#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
626
627/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
628 long) == 4. */
629
sewardj66226cc2006-01-20 15:46:46 +0000630#define CALL_FN_W_v(lval, orig) \
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[1]; \
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 __asm__ volatile( \
637 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
638 VALGRIND_CALL_NOREDIR_EAX \
639 : /*out*/ "=a" (_res) \
640 : /*in*/ "a" (&_argvec[0]) \
641 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
642 ); \
643 lval = (__typeof__(lval)) _res; \
644 } while (0)
645
sewardj66226cc2006-01-20 15:46:46 +0000646#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +0000647 do { \
sewardj66226cc2006-01-20 15:46:46 +0000648 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000649 volatile unsigned long _argvec[2]; \
650 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000651 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000652 _argvec[1] = (unsigned long)(arg1); \
653 __asm__ volatile( \
654 "pushl 4(%%eax)\n\t" \
655 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
656 VALGRIND_CALL_NOREDIR_EAX \
657 "addl $4, %%esp\n" \
658 : /*out*/ "=a" (_res) \
659 : /*in*/ "a" (&_argvec[0]) \
660 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
661 ); \
662 lval = (__typeof__(lval)) _res; \
663 } while (0)
664
sewardj66226cc2006-01-20 15:46:46 +0000665#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +0000666 do { \
sewardj66226cc2006-01-20 15:46:46 +0000667 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000668 volatile unsigned long _argvec[3]; \
669 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000670 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000671 _argvec[1] = (unsigned long)(arg1); \
672 _argvec[2] = (unsigned long)(arg2); \
673 __asm__ volatile( \
674 "pushl 8(%%eax)\n\t" \
675 "pushl 4(%%eax)\n\t" \
676 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
677 VALGRIND_CALL_NOREDIR_EAX \
678 "addl $8, %%esp\n" \
679 : /*out*/ "=a" (_res) \
680 : /*in*/ "a" (&_argvec[0]) \
681 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
682 ); \
683 lval = (__typeof__(lval)) _res; \
684 } while (0)
685
sewardj9e8b07a2006-02-18 21:13:29 +0000686#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
687 do { \
688 volatile OrigFn _orig = (orig); \
689 volatile unsigned long _argvec[4]; \
690 volatile unsigned long _res; \
691 _argvec[0] = (unsigned long)_orig.nraddr; \
692 _argvec[1] = (unsigned long)(arg1); \
693 _argvec[2] = (unsigned long)(arg2); \
694 _argvec[3] = (unsigned long)(arg3); \
695 __asm__ volatile( \
696 "pushl 12(%%eax)\n\t" \
697 "pushl 8(%%eax)\n\t" \
698 "pushl 4(%%eax)\n\t" \
699 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
700 VALGRIND_CALL_NOREDIR_EAX \
701 "addl $12, %%esp\n" \
702 : /*out*/ "=a" (_res) \
703 : /*in*/ "a" (&_argvec[0]) \
704 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
705 ); \
706 lval = (__typeof__(lval)) _res; \
707 } while (0)
708
sewardj66226cc2006-01-20 15:46:46 +0000709#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
sewardj0ec07f32006-01-12 12:32:32 +0000710 do { \
sewardj66226cc2006-01-20 15:46:46 +0000711 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000712 volatile unsigned long _argvec[5]; \
713 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000714 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000715 _argvec[1] = (unsigned long)(arg1); \
716 _argvec[2] = (unsigned long)(arg2); \
717 _argvec[3] = (unsigned long)(arg3); \
718 _argvec[4] = (unsigned long)(arg4); \
719 __asm__ volatile( \
720 "pushl 16(%%eax)\n\t" \
721 "pushl 12(%%eax)\n\t" \
722 "pushl 8(%%eax)\n\t" \
723 "pushl 4(%%eax)\n\t" \
724 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
725 VALGRIND_CALL_NOREDIR_EAX \
726 "addl $16, %%esp\n" \
727 : /*out*/ "=a" (_res) \
728 : /*in*/ "a" (&_argvec[0]) \
729 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
730 ); \
731 lval = (__typeof__(lval)) _res; \
732 } while (0)
733
sewardj66226cc2006-01-20 15:46:46 +0000734#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000735 do { \
sewardj66226cc2006-01-20 15:46:46 +0000736 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000737 volatile unsigned long _argvec[6]; \
738 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000739 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000740 _argvec[1] = (unsigned long)(arg1); \
741 _argvec[2] = (unsigned long)(arg2); \
742 _argvec[3] = (unsigned long)(arg3); \
743 _argvec[4] = (unsigned long)(arg4); \
744 _argvec[5] = (unsigned long)(arg5); \
745 __asm__ volatile( \
746 "pushl 20(%%eax)\n\t" \
747 "pushl 16(%%eax)\n\t" \
748 "pushl 12(%%eax)\n\t" \
749 "pushl 8(%%eax)\n\t" \
750 "pushl 4(%%eax)\n\t" \
751 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
752 VALGRIND_CALL_NOREDIR_EAX \
753 "addl $20, %%esp\n" \
754 : /*out*/ "=a" (_res) \
755 : /*in*/ "a" (&_argvec[0]) \
756 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
757 ); \
758 lval = (__typeof__(lval)) _res; \
759 } while (0)
760
sewardj66226cc2006-01-20 15:46:46 +0000761#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +0000762 do { \
sewardj66226cc2006-01-20 15:46:46 +0000763 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000764 volatile unsigned long _argvec[7]; \
765 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000766 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000767 _argvec[1] = (unsigned long)(arg1); \
768 _argvec[2] = (unsigned long)(arg2); \
769 _argvec[3] = (unsigned long)(arg3); \
770 _argvec[4] = (unsigned long)(arg4); \
771 _argvec[5] = (unsigned long)(arg5); \
772 _argvec[6] = (unsigned long)(arg6); \
773 __asm__ volatile( \
774 "pushl 24(%%eax)\n\t" \
775 "pushl 20(%%eax)\n\t" \
776 "pushl 16(%%eax)\n\t" \
777 "pushl 12(%%eax)\n\t" \
778 "pushl 8(%%eax)\n\t" \
779 "pushl 4(%%eax)\n\t" \
780 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
781 VALGRIND_CALL_NOREDIR_EAX \
782 "addl $24, %%esp\n" \
783 : /*out*/ "=a" (_res) \
784 : /*in*/ "a" (&_argvec[0]) \
785 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
786 ); \
787 lval = (__typeof__(lval)) _res; \
788 } while (0)
789
sewardj66226cc2006-01-20 15:46:46 +0000790#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
791 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +0000792 do { \
sewardj66226cc2006-01-20 15:46:46 +0000793 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000794 volatile unsigned long _argvec[8]; \
795 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000796 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000797 _argvec[1] = (unsigned long)(arg1); \
798 _argvec[2] = (unsigned long)(arg2); \
799 _argvec[3] = (unsigned long)(arg3); \
800 _argvec[4] = (unsigned long)(arg4); \
801 _argvec[5] = (unsigned long)(arg5); \
802 _argvec[6] = (unsigned long)(arg6); \
803 _argvec[7] = (unsigned long)(arg7); \
804 __asm__ volatile( \
805 "pushl 28(%%eax)\n\t" \
806 "pushl 24(%%eax)\n\t" \
807 "pushl 20(%%eax)\n\t" \
808 "pushl 16(%%eax)\n\t" \
809 "pushl 12(%%eax)\n\t" \
810 "pushl 8(%%eax)\n\t" \
811 "pushl 4(%%eax)\n\t" \
812 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
813 VALGRIND_CALL_NOREDIR_EAX \
814 "addl $28, %%esp\n" \
815 : /*out*/ "=a" (_res) \
816 : /*in*/ "a" (&_argvec[0]) \
817 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
818 ); \
819 lval = (__typeof__(lval)) _res; \
820 } while (0)
821
sewardj66226cc2006-01-20 15:46:46 +0000822#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
823 arg7,arg8) \
sewardj0ec07f32006-01-12 12:32:32 +0000824 do { \
sewardj66226cc2006-01-20 15:46:46 +0000825 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000826 volatile unsigned long _argvec[9]; \
827 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000828 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000829 _argvec[1] = (unsigned long)(arg1); \
830 _argvec[2] = (unsigned long)(arg2); \
831 _argvec[3] = (unsigned long)(arg3); \
832 _argvec[4] = (unsigned long)(arg4); \
833 _argvec[5] = (unsigned long)(arg5); \
834 _argvec[6] = (unsigned long)(arg6); \
835 _argvec[7] = (unsigned long)(arg7); \
836 _argvec[8] = (unsigned long)(arg8); \
837 __asm__ volatile( \
838 "pushl 32(%%eax)\n\t" \
839 "pushl 28(%%eax)\n\t" \
840 "pushl 24(%%eax)\n\t" \
841 "pushl 20(%%eax)\n\t" \
842 "pushl 16(%%eax)\n\t" \
843 "pushl 12(%%eax)\n\t" \
844 "pushl 8(%%eax)\n\t" \
845 "pushl 4(%%eax)\n\t" \
846 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
847 VALGRIND_CALL_NOREDIR_EAX \
848 "addl $32, %%esp\n" \
849 : /*out*/ "=a" (_res) \
850 : /*in*/ "a" (&_argvec[0]) \
851 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
852 ); \
853 lval = (__typeof__(lval)) _res; \
854 } while (0)
855
sewardj45fa5b02006-03-09 19:06:23 +0000856#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
857 arg7,arg8,arg9) \
858 do { \
859 volatile OrigFn _orig = (orig); \
860 volatile unsigned long _argvec[10]; \
861 volatile unsigned long _res; \
862 _argvec[0] = (unsigned long)_orig.nraddr; \
863 _argvec[1] = (unsigned long)(arg1); \
864 _argvec[2] = (unsigned long)(arg2); \
865 _argvec[3] = (unsigned long)(arg3); \
866 _argvec[4] = (unsigned long)(arg4); \
867 _argvec[5] = (unsigned long)(arg5); \
868 _argvec[6] = (unsigned long)(arg6); \
869 _argvec[7] = (unsigned long)(arg7); \
870 _argvec[8] = (unsigned long)(arg8); \
871 _argvec[9] = (unsigned long)(arg9); \
872 __asm__ volatile( \
873 "pushl 36(%%eax)\n\t" \
874 "pushl 32(%%eax)\n\t" \
875 "pushl 28(%%eax)\n\t" \
876 "pushl 24(%%eax)\n\t" \
877 "pushl 20(%%eax)\n\t" \
878 "pushl 16(%%eax)\n\t" \
879 "pushl 12(%%eax)\n\t" \
880 "pushl 8(%%eax)\n\t" \
881 "pushl 4(%%eax)\n\t" \
882 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
883 VALGRIND_CALL_NOREDIR_EAX \
884 "addl $36, %%esp\n" \
885 : /*out*/ "=a" (_res) \
886 : /*in*/ "a" (&_argvec[0]) \
887 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
888 ); \
889 lval = (__typeof__(lval)) _res; \
890 } while (0)
891
892#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
893 arg7,arg8,arg9,arg10) \
894 do { \
895 volatile OrigFn _orig = (orig); \
896 volatile unsigned long _argvec[11]; \
897 volatile unsigned long _res; \
898 _argvec[0] = (unsigned long)_orig.nraddr; \
899 _argvec[1] = (unsigned long)(arg1); \
900 _argvec[2] = (unsigned long)(arg2); \
901 _argvec[3] = (unsigned long)(arg3); \
902 _argvec[4] = (unsigned long)(arg4); \
903 _argvec[5] = (unsigned long)(arg5); \
904 _argvec[6] = (unsigned long)(arg6); \
905 _argvec[7] = (unsigned long)(arg7); \
906 _argvec[8] = (unsigned long)(arg8); \
907 _argvec[9] = (unsigned long)(arg9); \
908 _argvec[10] = (unsigned long)(arg10); \
909 __asm__ volatile( \
910 "pushl 40(%%eax)\n\t" \
911 "pushl 36(%%eax)\n\t" \
912 "pushl 32(%%eax)\n\t" \
913 "pushl 28(%%eax)\n\t" \
914 "pushl 24(%%eax)\n\t" \
915 "pushl 20(%%eax)\n\t" \
916 "pushl 16(%%eax)\n\t" \
917 "pushl 12(%%eax)\n\t" \
918 "pushl 8(%%eax)\n\t" \
919 "pushl 4(%%eax)\n\t" \
920 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
921 VALGRIND_CALL_NOREDIR_EAX \
922 "addl $40, %%esp\n" \
923 : /*out*/ "=a" (_res) \
924 : /*in*/ "a" (&_argvec[0]) \
925 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
926 ); \
927 lval = (__typeof__(lval)) _res; \
928 } while (0)
929
sewardj5ce4b152006-03-11 12:57:41 +0000930#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
931 arg6,arg7,arg8,arg9,arg10, \
932 arg11) \
933 do { \
934 volatile OrigFn _orig = (orig); \
935 volatile unsigned long _argvec[12]; \
936 volatile unsigned long _res; \
937 _argvec[0] = (unsigned long)_orig.nraddr; \
938 _argvec[1] = (unsigned long)(arg1); \
939 _argvec[2] = (unsigned long)(arg2); \
940 _argvec[3] = (unsigned long)(arg3); \
941 _argvec[4] = (unsigned long)(arg4); \
942 _argvec[5] = (unsigned long)(arg5); \
943 _argvec[6] = (unsigned long)(arg6); \
944 _argvec[7] = (unsigned long)(arg7); \
945 _argvec[8] = (unsigned long)(arg8); \
946 _argvec[9] = (unsigned long)(arg9); \
947 _argvec[10] = (unsigned long)(arg10); \
948 _argvec[11] = (unsigned long)(arg11); \
949 __asm__ volatile( \
950 "pushl 44(%%eax)\n\t" \
951 "pushl 40(%%eax)\n\t" \
952 "pushl 36(%%eax)\n\t" \
953 "pushl 32(%%eax)\n\t" \
954 "pushl 28(%%eax)\n\t" \
955 "pushl 24(%%eax)\n\t" \
956 "pushl 20(%%eax)\n\t" \
957 "pushl 16(%%eax)\n\t" \
958 "pushl 12(%%eax)\n\t" \
959 "pushl 8(%%eax)\n\t" \
960 "pushl 4(%%eax)\n\t" \
961 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
962 VALGRIND_CALL_NOREDIR_EAX \
963 "addl $44, %%esp\n" \
964 : /*out*/ "=a" (_res) \
965 : /*in*/ "a" (&_argvec[0]) \
966 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
967 ); \
968 lval = (__typeof__(lval)) _res; \
969 } while (0)
970
sewardj66226cc2006-01-20 15:46:46 +0000971#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
972 arg6,arg7,arg8,arg9,arg10, \
973 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +0000974 do { \
sewardj66226cc2006-01-20 15:46:46 +0000975 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000976 volatile unsigned long _argvec[13]; \
977 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000978 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000979 _argvec[1] = (unsigned long)(arg1); \
980 _argvec[2] = (unsigned long)(arg2); \
981 _argvec[3] = (unsigned long)(arg3); \
982 _argvec[4] = (unsigned long)(arg4); \
983 _argvec[5] = (unsigned long)(arg5); \
984 _argvec[6] = (unsigned long)(arg6); \
985 _argvec[7] = (unsigned long)(arg7); \
986 _argvec[8] = (unsigned long)(arg8); \
987 _argvec[9] = (unsigned long)(arg9); \
988 _argvec[10] = (unsigned long)(arg10); \
989 _argvec[11] = (unsigned long)(arg11); \
990 _argvec[12] = (unsigned long)(arg12); \
991 __asm__ volatile( \
992 "pushl 48(%%eax)\n\t" \
993 "pushl 44(%%eax)\n\t" \
994 "pushl 40(%%eax)\n\t" \
995 "pushl 36(%%eax)\n\t" \
996 "pushl 32(%%eax)\n\t" \
997 "pushl 28(%%eax)\n\t" \
998 "pushl 24(%%eax)\n\t" \
999 "pushl 20(%%eax)\n\t" \
1000 "pushl 16(%%eax)\n\t" \
1001 "pushl 12(%%eax)\n\t" \
1002 "pushl 8(%%eax)\n\t" \
1003 "pushl 4(%%eax)\n\t" \
1004 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1005 VALGRIND_CALL_NOREDIR_EAX \
1006 "addl $48, %%esp\n" \
1007 : /*out*/ "=a" (_res) \
1008 : /*in*/ "a" (&_argvec[0]) \
1009 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1010 ); \
1011 lval = (__typeof__(lval)) _res; \
1012 } while (0)
1013
sewardjf5c1a7f2006-10-17 01:32:48 +00001014#endif /* PLAT_x86_linux */
sewardj0ec07f32006-01-12 12:32:32 +00001015
sewardjf5c1a7f2006-10-17 01:32:48 +00001016/* ------------------------ amd64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00001017
sewardjf5c1a7f2006-10-17 01:32:48 +00001018#if defined(PLAT_amd64_linux)
sewardj0ec07f32006-01-12 12:32:32 +00001019
1020/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1021
1022/* These regs are trashed by the hidden call. */
1023#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1024 "rdi", "r8", "r9", "r10", "r11"
1025
1026/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1027 long) == 8. */
1028
sewardja07c2e12007-11-09 23:09:50 +00001029/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1030 macros. In order not to trash the stack redzone, we need to drop
1031 %rsp by 128 before the hidden call, and restore afterwards. The
1032 nastyness is that it is only by luck that the stack still appears
1033 to be unwindable during the hidden call - since then the behaviour
1034 of any routine using this macro does not match what the CFI data
1035 says. Sigh.
1036
1037 Why is this important? Imagine that a wrapper has a stack
1038 allocated local, and passes to the hidden call, a pointer to it.
1039 Because gcc does not know about the hidden call, it may allocate
1040 that local in the redzone. Unfortunately the hidden call may then
1041 trash it before it comes to use it. So we must step clear of the
1042 redzone, for the duration of the hidden call, to make it safe.
1043
1044 Probably the same problem afflicts the other redzone-style ABIs too
1045 (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
1046 self describing (none of this CFI nonsense) so at least messing
1047 with the stack pointer doesn't give a danger of non-unwindable
1048 stack. */
1049
sewardjc8858442006-01-20 15:17:20 +00001050#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001051 do { \
sewardjc8858442006-01-20 15:17:20 +00001052 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001053 volatile unsigned long _argvec[1]; \
1054 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001055 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001056 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001057 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001058 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1059 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001060 "addq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001061 : /*out*/ "=a" (_res) \
1062 : /*in*/ "a" (&_argvec[0]) \
1063 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1064 ); \
1065 lval = (__typeof__(lval)) _res; \
1066 } while (0)
1067
sewardjc8858442006-01-20 15:17:20 +00001068#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001069 do { \
sewardjc8858442006-01-20 15:17:20 +00001070 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001071 volatile unsigned long _argvec[2]; \
1072 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001073 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001074 _argvec[1] = (unsigned long)(arg1); \
1075 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001076 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001077 "movq 8(%%rax), %%rdi\n\t" \
1078 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1079 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001080 "addq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001081 : /*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
sewardjc8858442006-01-20 15:17:20 +00001088#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001089 do { \
sewardjc8858442006-01-20 15:17:20 +00001090 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001091 volatile unsigned long _argvec[3]; \
1092 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001093 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001094 _argvec[1] = (unsigned long)(arg1); \
1095 _argvec[2] = (unsigned long)(arg2); \
1096 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001097 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001098 "movq 16(%%rax), %%rsi\n\t" \
1099 "movq 8(%%rax), %%rdi\n\t" \
1100 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1101 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001102 "addq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001103 : /*out*/ "=a" (_res) \
1104 : /*in*/ "a" (&_argvec[0]) \
1105 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1106 ); \
1107 lval = (__typeof__(lval)) _res; \
1108 } while (0)
1109
sewardja50f9dc2006-03-11 16:19:14 +00001110#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1111 do { \
1112 volatile OrigFn _orig = (orig); \
1113 volatile unsigned long _argvec[4]; \
1114 volatile unsigned long _res; \
1115 _argvec[0] = (unsigned long)_orig.nraddr; \
1116 _argvec[1] = (unsigned long)(arg1); \
1117 _argvec[2] = (unsigned long)(arg2); \
1118 _argvec[3] = (unsigned long)(arg3); \
1119 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001120 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001121 "movq 24(%%rax), %%rdx\n\t" \
1122 "movq 16(%%rax), %%rsi\n\t" \
1123 "movq 8(%%rax), %%rdi\n\t" \
1124 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1125 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001126 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001127 : /*out*/ "=a" (_res) \
1128 : /*in*/ "a" (&_argvec[0]) \
1129 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1130 ); \
1131 lval = (__typeof__(lval)) _res; \
1132 } while (0)
1133
1134#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1135 do { \
1136 volatile OrigFn _orig = (orig); \
1137 volatile unsigned long _argvec[5]; \
1138 volatile unsigned long _res; \
1139 _argvec[0] = (unsigned long)_orig.nraddr; \
1140 _argvec[1] = (unsigned long)(arg1); \
1141 _argvec[2] = (unsigned long)(arg2); \
1142 _argvec[3] = (unsigned long)(arg3); \
1143 _argvec[4] = (unsigned long)(arg4); \
1144 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001145 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001146 "movq 32(%%rax), %%rcx\n\t" \
1147 "movq 24(%%rax), %%rdx\n\t" \
1148 "movq 16(%%rax), %%rsi\n\t" \
1149 "movq 8(%%rax), %%rdi\n\t" \
1150 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1151 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001152 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001153 : /*out*/ "=a" (_res) \
1154 : /*in*/ "a" (&_argvec[0]) \
1155 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1156 ); \
1157 lval = (__typeof__(lval)) _res; \
1158 } while (0)
1159
1160#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1161 do { \
1162 volatile OrigFn _orig = (orig); \
1163 volatile unsigned long _argvec[6]; \
1164 volatile unsigned long _res; \
1165 _argvec[0] = (unsigned long)_orig.nraddr; \
1166 _argvec[1] = (unsigned long)(arg1); \
1167 _argvec[2] = (unsigned long)(arg2); \
1168 _argvec[3] = (unsigned long)(arg3); \
1169 _argvec[4] = (unsigned long)(arg4); \
1170 _argvec[5] = (unsigned long)(arg5); \
1171 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001172 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001173 "movq 40(%%rax), %%r8\n\t" \
1174 "movq 32(%%rax), %%rcx\n\t" \
1175 "movq 24(%%rax), %%rdx\n\t" \
1176 "movq 16(%%rax), %%rsi\n\t" \
1177 "movq 8(%%rax), %%rdi\n\t" \
1178 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1179 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001180 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001181 : /*out*/ "=a" (_res) \
1182 : /*in*/ "a" (&_argvec[0]) \
1183 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1184 ); \
1185 lval = (__typeof__(lval)) _res; \
1186 } while (0)
1187
1188#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1189 do { \
1190 volatile OrigFn _orig = (orig); \
1191 volatile unsigned long _argvec[7]; \
1192 volatile unsigned long _res; \
1193 _argvec[0] = (unsigned long)_orig.nraddr; \
1194 _argvec[1] = (unsigned long)(arg1); \
1195 _argvec[2] = (unsigned long)(arg2); \
1196 _argvec[3] = (unsigned long)(arg3); \
1197 _argvec[4] = (unsigned long)(arg4); \
1198 _argvec[5] = (unsigned long)(arg5); \
1199 _argvec[6] = (unsigned long)(arg6); \
1200 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001201 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001202 "movq 48(%%rax), %%r9\n\t" \
1203 "movq 40(%%rax), %%r8\n\t" \
1204 "movq 32(%%rax), %%rcx\n\t" \
1205 "movq 24(%%rax), %%rdx\n\t" \
1206 "movq 16(%%rax), %%rsi\n\t" \
1207 "movq 8(%%rax), %%rdi\n\t" \
1208 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
sewardja07c2e12007-11-09 23:09:50 +00001209 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001210 VALGRIND_CALL_NOREDIR_RAX \
1211 : /*out*/ "=a" (_res) \
1212 : /*in*/ "a" (&_argvec[0]) \
1213 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1214 ); \
1215 lval = (__typeof__(lval)) _res; \
1216 } while (0)
1217
1218#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1219 arg7) \
1220 do { \
1221 volatile OrigFn _orig = (orig); \
1222 volatile unsigned long _argvec[8]; \
1223 volatile unsigned long _res; \
1224 _argvec[0] = (unsigned long)_orig.nraddr; \
1225 _argvec[1] = (unsigned long)(arg1); \
1226 _argvec[2] = (unsigned long)(arg2); \
1227 _argvec[3] = (unsigned long)(arg3); \
1228 _argvec[4] = (unsigned long)(arg4); \
1229 _argvec[5] = (unsigned long)(arg5); \
1230 _argvec[6] = (unsigned long)(arg6); \
1231 _argvec[7] = (unsigned long)(arg7); \
1232 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001233 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001234 "pushq 56(%%rax)\n\t" \
1235 "movq 48(%%rax), %%r9\n\t" \
1236 "movq 40(%%rax), %%r8\n\t" \
1237 "movq 32(%%rax), %%rcx\n\t" \
1238 "movq 24(%%rax), %%rdx\n\t" \
1239 "movq 16(%%rax), %%rsi\n\t" \
1240 "movq 8(%%rax), %%rdi\n\t" \
1241 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1242 VALGRIND_CALL_NOREDIR_RAX \
1243 "addq $8, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001244 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001245 : /*out*/ "=a" (_res) \
1246 : /*in*/ "a" (&_argvec[0]) \
1247 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1248 ); \
1249 lval = (__typeof__(lval)) _res; \
1250 } while (0)
1251
1252#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1253 arg7,arg8) \
1254 do { \
1255 volatile OrigFn _orig = (orig); \
1256 volatile unsigned long _argvec[9]; \
1257 volatile unsigned long _res; \
1258 _argvec[0] = (unsigned long)_orig.nraddr; \
1259 _argvec[1] = (unsigned long)(arg1); \
1260 _argvec[2] = (unsigned long)(arg2); \
1261 _argvec[3] = (unsigned long)(arg3); \
1262 _argvec[4] = (unsigned long)(arg4); \
1263 _argvec[5] = (unsigned long)(arg5); \
1264 _argvec[6] = (unsigned long)(arg6); \
1265 _argvec[7] = (unsigned long)(arg7); \
1266 _argvec[8] = (unsigned long)(arg8); \
1267 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001268 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001269 "pushq 64(%%rax)\n\t" \
1270 "pushq 56(%%rax)\n\t" \
1271 "movq 48(%%rax), %%r9\n\t" \
1272 "movq 40(%%rax), %%r8\n\t" \
1273 "movq 32(%%rax), %%rcx\n\t" \
1274 "movq 24(%%rax), %%rdx\n\t" \
1275 "movq 16(%%rax), %%rsi\n\t" \
1276 "movq 8(%%rax), %%rdi\n\t" \
1277 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1278 VALGRIND_CALL_NOREDIR_RAX \
1279 "addq $16, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001280 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001281 : /*out*/ "=a" (_res) \
1282 : /*in*/ "a" (&_argvec[0]) \
1283 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1284 ); \
1285 lval = (__typeof__(lval)) _res; \
1286 } while (0)
1287
1288#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1289 arg7,arg8,arg9) \
1290 do { \
1291 volatile OrigFn _orig = (orig); \
1292 volatile unsigned long _argvec[10]; \
1293 volatile unsigned long _res; \
1294 _argvec[0] = (unsigned long)_orig.nraddr; \
1295 _argvec[1] = (unsigned long)(arg1); \
1296 _argvec[2] = (unsigned long)(arg2); \
1297 _argvec[3] = (unsigned long)(arg3); \
1298 _argvec[4] = (unsigned long)(arg4); \
1299 _argvec[5] = (unsigned long)(arg5); \
1300 _argvec[6] = (unsigned long)(arg6); \
1301 _argvec[7] = (unsigned long)(arg7); \
1302 _argvec[8] = (unsigned long)(arg8); \
1303 _argvec[9] = (unsigned long)(arg9); \
1304 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001305 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001306 "pushq 72(%%rax)\n\t" \
1307 "pushq 64(%%rax)\n\t" \
1308 "pushq 56(%%rax)\n\t" \
1309 "movq 48(%%rax), %%r9\n\t" \
1310 "movq 40(%%rax), %%r8\n\t" \
1311 "movq 32(%%rax), %%rcx\n\t" \
1312 "movq 24(%%rax), %%rdx\n\t" \
1313 "movq 16(%%rax), %%rsi\n\t" \
1314 "movq 8(%%rax), %%rdi\n\t" \
1315 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1316 VALGRIND_CALL_NOREDIR_RAX \
1317 "addq $24, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001318 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001319 : /*out*/ "=a" (_res) \
1320 : /*in*/ "a" (&_argvec[0]) \
1321 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1322 ); \
1323 lval = (__typeof__(lval)) _res; \
1324 } while (0)
1325
1326#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1327 arg7,arg8,arg9,arg10) \
1328 do { \
1329 volatile OrigFn _orig = (orig); \
1330 volatile unsigned long _argvec[11]; \
1331 volatile unsigned long _res; \
1332 _argvec[0] = (unsigned long)_orig.nraddr; \
1333 _argvec[1] = (unsigned long)(arg1); \
1334 _argvec[2] = (unsigned long)(arg2); \
1335 _argvec[3] = (unsigned long)(arg3); \
1336 _argvec[4] = (unsigned long)(arg4); \
1337 _argvec[5] = (unsigned long)(arg5); \
1338 _argvec[6] = (unsigned long)(arg6); \
1339 _argvec[7] = (unsigned long)(arg7); \
1340 _argvec[8] = (unsigned long)(arg8); \
1341 _argvec[9] = (unsigned long)(arg9); \
1342 _argvec[10] = (unsigned long)(arg10); \
1343 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001344 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001345 "pushq 80(%%rax)\n\t" \
1346 "pushq 72(%%rax)\n\t" \
1347 "pushq 64(%%rax)\n\t" \
1348 "pushq 56(%%rax)\n\t" \
1349 "movq 48(%%rax), %%r9\n\t" \
1350 "movq 40(%%rax), %%r8\n\t" \
1351 "movq 32(%%rax), %%rcx\n\t" \
1352 "movq 24(%%rax), %%rdx\n\t" \
1353 "movq 16(%%rax), %%rsi\n\t" \
1354 "movq 8(%%rax), %%rdi\n\t" \
1355 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1356 VALGRIND_CALL_NOREDIR_RAX \
1357 "addq $32, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001358 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001359 : /*out*/ "=a" (_res) \
1360 : /*in*/ "a" (&_argvec[0]) \
1361 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1362 ); \
1363 lval = (__typeof__(lval)) _res; \
1364 } while (0)
1365
1366#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1367 arg7,arg8,arg9,arg10,arg11) \
1368 do { \
1369 volatile OrigFn _orig = (orig); \
1370 volatile unsigned long _argvec[12]; \
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 _argvec[5] = (unsigned long)(arg5); \
1378 _argvec[6] = (unsigned long)(arg6); \
1379 _argvec[7] = (unsigned long)(arg7); \
1380 _argvec[8] = (unsigned long)(arg8); \
1381 _argvec[9] = (unsigned long)(arg9); \
1382 _argvec[10] = (unsigned long)(arg10); \
1383 _argvec[11] = (unsigned long)(arg11); \
1384 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001385 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001386 "pushq 88(%%rax)\n\t" \
1387 "pushq 80(%%rax)\n\t" \
1388 "pushq 72(%%rax)\n\t" \
1389 "pushq 64(%%rax)\n\t" \
1390 "pushq 56(%%rax)\n\t" \
1391 "movq 48(%%rax), %%r9\n\t" \
1392 "movq 40(%%rax), %%r8\n\t" \
1393 "movq 32(%%rax), %%rcx\n\t" \
1394 "movq 24(%%rax), %%rdx\n\t" \
1395 "movq 16(%%rax), %%rsi\n\t" \
1396 "movq 8(%%rax), %%rdi\n\t" \
1397 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1398 VALGRIND_CALL_NOREDIR_RAX \
1399 "addq $40, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001400 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001401 : /*out*/ "=a" (_res) \
1402 : /*in*/ "a" (&_argvec[0]) \
1403 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1404 ); \
1405 lval = (__typeof__(lval)) _res; \
1406 } while (0)
1407
1408#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1409 arg7,arg8,arg9,arg10,arg11,arg12) \
1410 do { \
1411 volatile OrigFn _orig = (orig); \
1412 volatile unsigned long _argvec[13]; \
1413 volatile unsigned long _res; \
1414 _argvec[0] = (unsigned long)_orig.nraddr; \
1415 _argvec[1] = (unsigned long)(arg1); \
1416 _argvec[2] = (unsigned long)(arg2); \
1417 _argvec[3] = (unsigned long)(arg3); \
1418 _argvec[4] = (unsigned long)(arg4); \
1419 _argvec[5] = (unsigned long)(arg5); \
1420 _argvec[6] = (unsigned long)(arg6); \
1421 _argvec[7] = (unsigned long)(arg7); \
1422 _argvec[8] = (unsigned long)(arg8); \
1423 _argvec[9] = (unsigned long)(arg9); \
1424 _argvec[10] = (unsigned long)(arg10); \
1425 _argvec[11] = (unsigned long)(arg11); \
1426 _argvec[12] = (unsigned long)(arg12); \
1427 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001428 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001429 "pushq 96(%%rax)\n\t" \
1430 "pushq 88(%%rax)\n\t" \
1431 "pushq 80(%%rax)\n\t" \
1432 "pushq 72(%%rax)\n\t" \
1433 "pushq 64(%%rax)\n\t" \
1434 "pushq 56(%%rax)\n\t" \
1435 "movq 48(%%rax), %%r9\n\t" \
1436 "movq 40(%%rax), %%r8\n\t" \
1437 "movq 32(%%rax), %%rcx\n\t" \
1438 "movq 24(%%rax), %%rdx\n\t" \
1439 "movq 16(%%rax), %%rsi\n\t" \
1440 "movq 8(%%rax), %%rdi\n\t" \
1441 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1442 VALGRIND_CALL_NOREDIR_RAX \
1443 "addq $48, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001444 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001445 : /*out*/ "=a" (_res) \
1446 : /*in*/ "a" (&_argvec[0]) \
1447 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1448 ); \
1449 lval = (__typeof__(lval)) _res; \
1450 } while (0)
1451
sewardjf5c1a7f2006-10-17 01:32:48 +00001452#endif /* PLAT_amd64_linux */
sewardj0ec07f32006-01-12 12:32:32 +00001453
sewardjf5c1a7f2006-10-17 01:32:48 +00001454/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00001455
sewardjf5c1a7f2006-10-17 01:32:48 +00001456#if defined(PLAT_ppc32_linux)
sewardj0ec07f32006-01-12 12:32:32 +00001457
sewardjead61df2006-03-12 13:39:15 +00001458/* This is useful for finding out about the on-stack stuff:
1459
1460 extern int f9 ( int,int,int,int,int,int,int,int,int );
1461 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1462 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1463 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1464
1465 int g9 ( void ) {
1466 return f9(11,22,33,44,55,66,77,88,99);
1467 }
1468 int g10 ( void ) {
1469 return f10(11,22,33,44,55,66,77,88,99,110);
1470 }
1471 int g11 ( void ) {
1472 return f11(11,22,33,44,55,66,77,88,99,110,121);
1473 }
1474 int g12 ( void ) {
1475 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1476 }
1477*/
1478
sewardj0ec07f32006-01-12 12:32:32 +00001479/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1480
1481/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00001482#define __CALLER_SAVED_REGS \
1483 "lr", "ctr", "xer", \
1484 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1485 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1486 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00001487
sewardjead61df2006-03-12 13:39:15 +00001488/* These CALL_FN_ macros assume that on ppc32-linux,
1489 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00001490
sewardj38de0992006-01-20 16:46:34 +00001491#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001492 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001493 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001494 volatile unsigned long _argvec[1]; \
1495 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001496 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001497 __asm__ volatile( \
1498 "mr 11,%1\n\t" \
1499 "lwz 11,0(11)\n\t" /* target->r11 */ \
1500 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1501 "mr %0,3" \
1502 : /*out*/ "=r" (_res) \
1503 : /*in*/ "r" (&_argvec[0]) \
1504 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1505 ); \
1506 lval = (__typeof__(lval)) _res; \
1507 } while (0)
1508
sewardj38de0992006-01-20 16:46:34 +00001509#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001510 do { \
sewardj38de0992006-01-20 16:46:34 +00001511 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001512 volatile unsigned long _argvec[2]; \
1513 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001514 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001515 _argvec[1] = (unsigned long)arg1; \
1516 __asm__ volatile( \
1517 "mr 11,%1\n\t" \
1518 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1519 "lwz 11,0(11)\n\t" /* target->r11 */ \
1520 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1521 "mr %0,3" \
1522 : /*out*/ "=r" (_res) \
1523 : /*in*/ "r" (&_argvec[0]) \
1524 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1525 ); \
1526 lval = (__typeof__(lval)) _res; \
1527 } while (0)
1528
sewardj38de0992006-01-20 16:46:34 +00001529#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001530 do { \
sewardj38de0992006-01-20 16:46:34 +00001531 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001532 volatile unsigned long _argvec[3]; \
1533 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001534 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001535 _argvec[1] = (unsigned long)arg1; \
1536 _argvec[2] = (unsigned long)arg2; \
1537 __asm__ volatile( \
1538 "mr 11,%1\n\t" \
1539 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1540 "lwz 4,8(11)\n\t" \
1541 "lwz 11,0(11)\n\t" /* target->r11 */ \
1542 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1543 "mr %0,3" \
1544 : /*out*/ "=r" (_res) \
1545 : /*in*/ "r" (&_argvec[0]) \
1546 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1547 ); \
1548 lval = (__typeof__(lval)) _res; \
1549 } while (0)
1550
sewardjead61df2006-03-12 13:39:15 +00001551#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1552 do { \
1553 volatile OrigFn _orig = (orig); \
1554 volatile unsigned long _argvec[4]; \
1555 volatile unsigned long _res; \
1556 _argvec[0] = (unsigned long)_orig.nraddr; \
1557 _argvec[1] = (unsigned long)arg1; \
1558 _argvec[2] = (unsigned long)arg2; \
1559 _argvec[3] = (unsigned long)arg3; \
1560 __asm__ volatile( \
1561 "mr 11,%1\n\t" \
1562 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1563 "lwz 4,8(11)\n\t" \
1564 "lwz 5,12(11)\n\t" \
1565 "lwz 11,0(11)\n\t" /* target->r11 */ \
1566 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1567 "mr %0,3" \
1568 : /*out*/ "=r" (_res) \
1569 : /*in*/ "r" (&_argvec[0]) \
1570 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1571 ); \
1572 lval = (__typeof__(lval)) _res; \
1573 } while (0)
1574
1575#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1576 do { \
1577 volatile OrigFn _orig = (orig); \
1578 volatile unsigned long _argvec[5]; \
1579 volatile unsigned long _res; \
1580 _argvec[0] = (unsigned long)_orig.nraddr; \
1581 _argvec[1] = (unsigned long)arg1; \
1582 _argvec[2] = (unsigned long)arg2; \
1583 _argvec[3] = (unsigned long)arg3; \
1584 _argvec[4] = (unsigned long)arg4; \
1585 __asm__ volatile( \
1586 "mr 11,%1\n\t" \
1587 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1588 "lwz 4,8(11)\n\t" \
1589 "lwz 5,12(11)\n\t" \
1590 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1591 "lwz 11,0(11)\n\t" /* target->r11 */ \
1592 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1593 "mr %0,3" \
1594 : /*out*/ "=r" (_res) \
1595 : /*in*/ "r" (&_argvec[0]) \
1596 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1597 ); \
1598 lval = (__typeof__(lval)) _res; \
1599 } while (0)
1600
1601#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1602 do { \
1603 volatile OrigFn _orig = (orig); \
1604 volatile unsigned long _argvec[6]; \
1605 volatile unsigned long _res; \
1606 _argvec[0] = (unsigned long)_orig.nraddr; \
1607 _argvec[1] = (unsigned long)arg1; \
1608 _argvec[2] = (unsigned long)arg2; \
1609 _argvec[3] = (unsigned long)arg3; \
1610 _argvec[4] = (unsigned long)arg4; \
1611 _argvec[5] = (unsigned long)arg5; \
1612 __asm__ volatile( \
1613 "mr 11,%1\n\t" \
1614 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1615 "lwz 4,8(11)\n\t" \
1616 "lwz 5,12(11)\n\t" \
1617 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1618 "lwz 7,20(11)\n\t" \
1619 "lwz 11,0(11)\n\t" /* target->r11 */ \
1620 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1621 "mr %0,3" \
1622 : /*out*/ "=r" (_res) \
1623 : /*in*/ "r" (&_argvec[0]) \
1624 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1625 ); \
1626 lval = (__typeof__(lval)) _res; \
1627 } while (0)
1628
1629#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1630 do { \
1631 volatile OrigFn _orig = (orig); \
1632 volatile unsigned long _argvec[7]; \
1633 volatile unsigned long _res; \
1634 _argvec[0] = (unsigned long)_orig.nraddr; \
1635 _argvec[1] = (unsigned long)arg1; \
1636 _argvec[2] = (unsigned long)arg2; \
1637 _argvec[3] = (unsigned long)arg3; \
1638 _argvec[4] = (unsigned long)arg4; \
1639 _argvec[5] = (unsigned long)arg5; \
1640 _argvec[6] = (unsigned long)arg6; \
1641 __asm__ volatile( \
1642 "mr 11,%1\n\t" \
1643 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1644 "lwz 4,8(11)\n\t" \
1645 "lwz 5,12(11)\n\t" \
1646 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1647 "lwz 7,20(11)\n\t" \
1648 "lwz 8,24(11)\n\t" \
1649 "lwz 11,0(11)\n\t" /* target->r11 */ \
1650 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1651 "mr %0,3" \
1652 : /*out*/ "=r" (_res) \
1653 : /*in*/ "r" (&_argvec[0]) \
1654 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1655 ); \
1656 lval = (__typeof__(lval)) _res; \
1657 } while (0)
1658
1659#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1660 arg7) \
1661 do { \
1662 volatile OrigFn _orig = (orig); \
1663 volatile unsigned long _argvec[8]; \
1664 volatile unsigned long _res; \
1665 _argvec[0] = (unsigned long)_orig.nraddr; \
1666 _argvec[1] = (unsigned long)arg1; \
1667 _argvec[2] = (unsigned long)arg2; \
1668 _argvec[3] = (unsigned long)arg3; \
1669 _argvec[4] = (unsigned long)arg4; \
1670 _argvec[5] = (unsigned long)arg5; \
1671 _argvec[6] = (unsigned long)arg6; \
1672 _argvec[7] = (unsigned long)arg7; \
1673 __asm__ volatile( \
1674 "mr 11,%1\n\t" \
1675 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1676 "lwz 4,8(11)\n\t" \
1677 "lwz 5,12(11)\n\t" \
1678 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1679 "lwz 7,20(11)\n\t" \
1680 "lwz 8,24(11)\n\t" \
1681 "lwz 9,28(11)\n\t" \
1682 "lwz 11,0(11)\n\t" /* target->r11 */ \
1683 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1684 "mr %0,3" \
1685 : /*out*/ "=r" (_res) \
1686 : /*in*/ "r" (&_argvec[0]) \
1687 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1688 ); \
1689 lval = (__typeof__(lval)) _res; \
1690 } while (0)
1691
1692#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1693 arg7,arg8) \
1694 do { \
1695 volatile OrigFn _orig = (orig); \
1696 volatile unsigned long _argvec[9]; \
1697 volatile unsigned long _res; \
1698 _argvec[0] = (unsigned long)_orig.nraddr; \
1699 _argvec[1] = (unsigned long)arg1; \
1700 _argvec[2] = (unsigned long)arg2; \
1701 _argvec[3] = (unsigned long)arg3; \
1702 _argvec[4] = (unsigned long)arg4; \
1703 _argvec[5] = (unsigned long)arg5; \
1704 _argvec[6] = (unsigned long)arg6; \
1705 _argvec[7] = (unsigned long)arg7; \
1706 _argvec[8] = (unsigned long)arg8; \
1707 __asm__ volatile( \
1708 "mr 11,%1\n\t" \
1709 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1710 "lwz 4,8(11)\n\t" \
1711 "lwz 5,12(11)\n\t" \
1712 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1713 "lwz 7,20(11)\n\t" \
1714 "lwz 8,24(11)\n\t" \
1715 "lwz 9,28(11)\n\t" \
1716 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1717 "lwz 11,0(11)\n\t" /* target->r11 */ \
1718 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1719 "mr %0,3" \
1720 : /*out*/ "=r" (_res) \
1721 : /*in*/ "r" (&_argvec[0]) \
1722 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1723 ); \
1724 lval = (__typeof__(lval)) _res; \
1725 } while (0)
1726
1727#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1728 arg7,arg8,arg9) \
1729 do { \
1730 volatile OrigFn _orig = (orig); \
1731 volatile unsigned long _argvec[10]; \
1732 volatile unsigned long _res; \
1733 _argvec[0] = (unsigned long)_orig.nraddr; \
1734 _argvec[1] = (unsigned long)arg1; \
1735 _argvec[2] = (unsigned long)arg2; \
1736 _argvec[3] = (unsigned long)arg3; \
1737 _argvec[4] = (unsigned long)arg4; \
1738 _argvec[5] = (unsigned long)arg5; \
1739 _argvec[6] = (unsigned long)arg6; \
1740 _argvec[7] = (unsigned long)arg7; \
1741 _argvec[8] = (unsigned long)arg8; \
1742 _argvec[9] = (unsigned long)arg9; \
1743 __asm__ volatile( \
1744 "mr 11,%1\n\t" \
1745 "addi 1,1,-16\n\t" \
1746 /* arg9 */ \
1747 "lwz 3,36(11)\n\t" \
1748 "stw 3,8(1)\n\t" \
1749 /* args1-8 */ \
1750 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1751 "lwz 4,8(11)\n\t" \
1752 "lwz 5,12(11)\n\t" \
1753 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1754 "lwz 7,20(11)\n\t" \
1755 "lwz 8,24(11)\n\t" \
1756 "lwz 9,28(11)\n\t" \
1757 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1758 "lwz 11,0(11)\n\t" /* target->r11 */ \
1759 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1760 "addi 1,1,16\n\t" \
1761 "mr %0,3" \
1762 : /*out*/ "=r" (_res) \
1763 : /*in*/ "r" (&_argvec[0]) \
1764 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1765 ); \
1766 lval = (__typeof__(lval)) _res; \
1767 } while (0)
1768
1769#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1770 arg7,arg8,arg9,arg10) \
1771 do { \
1772 volatile OrigFn _orig = (orig); \
1773 volatile unsigned long _argvec[11]; \
1774 volatile unsigned long _res; \
1775 _argvec[0] = (unsigned long)_orig.nraddr; \
1776 _argvec[1] = (unsigned long)arg1; \
1777 _argvec[2] = (unsigned long)arg2; \
1778 _argvec[3] = (unsigned long)arg3; \
1779 _argvec[4] = (unsigned long)arg4; \
1780 _argvec[5] = (unsigned long)arg5; \
1781 _argvec[6] = (unsigned long)arg6; \
1782 _argvec[7] = (unsigned long)arg7; \
1783 _argvec[8] = (unsigned long)arg8; \
1784 _argvec[9] = (unsigned long)arg9; \
1785 _argvec[10] = (unsigned long)arg10; \
1786 __asm__ volatile( \
1787 "mr 11,%1\n\t" \
1788 "addi 1,1,-16\n\t" \
1789 /* arg10 */ \
1790 "lwz 3,40(11)\n\t" \
1791 "stw 3,12(1)\n\t" \
1792 /* arg9 */ \
1793 "lwz 3,36(11)\n\t" \
1794 "stw 3,8(1)\n\t" \
1795 /* args1-8 */ \
1796 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1797 "lwz 4,8(11)\n\t" \
1798 "lwz 5,12(11)\n\t" \
1799 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1800 "lwz 7,20(11)\n\t" \
1801 "lwz 8,24(11)\n\t" \
1802 "lwz 9,28(11)\n\t" \
1803 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1804 "lwz 11,0(11)\n\t" /* target->r11 */ \
1805 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1806 "addi 1,1,16\n\t" \
1807 "mr %0,3" \
1808 : /*out*/ "=r" (_res) \
1809 : /*in*/ "r" (&_argvec[0]) \
1810 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1811 ); \
1812 lval = (__typeof__(lval)) _res; \
1813 } while (0)
1814
1815#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1816 arg7,arg8,arg9,arg10,arg11) \
1817 do { \
1818 volatile OrigFn _orig = (orig); \
1819 volatile unsigned long _argvec[12]; \
1820 volatile unsigned long _res; \
1821 _argvec[0] = (unsigned long)_orig.nraddr; \
1822 _argvec[1] = (unsigned long)arg1; \
1823 _argvec[2] = (unsigned long)arg2; \
1824 _argvec[3] = (unsigned long)arg3; \
1825 _argvec[4] = (unsigned long)arg4; \
1826 _argvec[5] = (unsigned long)arg5; \
1827 _argvec[6] = (unsigned long)arg6; \
1828 _argvec[7] = (unsigned long)arg7; \
1829 _argvec[8] = (unsigned long)arg8; \
1830 _argvec[9] = (unsigned long)arg9; \
1831 _argvec[10] = (unsigned long)arg10; \
1832 _argvec[11] = (unsigned long)arg11; \
1833 __asm__ volatile( \
1834 "mr 11,%1\n\t" \
1835 "addi 1,1,-32\n\t" \
1836 /* arg11 */ \
1837 "lwz 3,44(11)\n\t" \
1838 "stw 3,16(1)\n\t" \
1839 /* arg10 */ \
1840 "lwz 3,40(11)\n\t" \
1841 "stw 3,12(1)\n\t" \
1842 /* arg9 */ \
1843 "lwz 3,36(11)\n\t" \
1844 "stw 3,8(1)\n\t" \
1845 /* args1-8 */ \
1846 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1847 "lwz 4,8(11)\n\t" \
1848 "lwz 5,12(11)\n\t" \
1849 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1850 "lwz 7,20(11)\n\t" \
1851 "lwz 8,24(11)\n\t" \
1852 "lwz 9,28(11)\n\t" \
1853 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1854 "lwz 11,0(11)\n\t" /* target->r11 */ \
1855 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1856 "addi 1,1,32\n\t" \
1857 "mr %0,3" \
1858 : /*out*/ "=r" (_res) \
1859 : /*in*/ "r" (&_argvec[0]) \
1860 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1861 ); \
1862 lval = (__typeof__(lval)) _res; \
1863 } while (0)
1864
1865#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1866 arg7,arg8,arg9,arg10,arg11,arg12) \
1867 do { \
1868 volatile OrigFn _orig = (orig); \
1869 volatile unsigned long _argvec[13]; \
1870 volatile unsigned long _res; \
1871 _argvec[0] = (unsigned long)_orig.nraddr; \
1872 _argvec[1] = (unsigned long)arg1; \
1873 _argvec[2] = (unsigned long)arg2; \
1874 _argvec[3] = (unsigned long)arg3; \
1875 _argvec[4] = (unsigned long)arg4; \
1876 _argvec[5] = (unsigned long)arg5; \
1877 _argvec[6] = (unsigned long)arg6; \
1878 _argvec[7] = (unsigned long)arg7; \
1879 _argvec[8] = (unsigned long)arg8; \
1880 _argvec[9] = (unsigned long)arg9; \
1881 _argvec[10] = (unsigned long)arg10; \
1882 _argvec[11] = (unsigned long)arg11; \
1883 _argvec[12] = (unsigned long)arg12; \
1884 __asm__ volatile( \
1885 "mr 11,%1\n\t" \
1886 "addi 1,1,-32\n\t" \
1887 /* arg12 */ \
1888 "lwz 3,48(11)\n\t" \
1889 "stw 3,20(1)\n\t" \
1890 /* arg11 */ \
1891 "lwz 3,44(11)\n\t" \
1892 "stw 3,16(1)\n\t" \
1893 /* arg10 */ \
1894 "lwz 3,40(11)\n\t" \
1895 "stw 3,12(1)\n\t" \
1896 /* arg9 */ \
1897 "lwz 3,36(11)\n\t" \
1898 "stw 3,8(1)\n\t" \
1899 /* args1-8 */ \
1900 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1901 "lwz 4,8(11)\n\t" \
1902 "lwz 5,12(11)\n\t" \
1903 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1904 "lwz 7,20(11)\n\t" \
1905 "lwz 8,24(11)\n\t" \
1906 "lwz 9,28(11)\n\t" \
1907 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1908 "lwz 11,0(11)\n\t" /* target->r11 */ \
1909 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1910 "addi 1,1,32\n\t" \
1911 "mr %0,3" \
1912 : /*out*/ "=r" (_res) \
1913 : /*in*/ "r" (&_argvec[0]) \
1914 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1915 ); \
1916 lval = (__typeof__(lval)) _res; \
1917 } while (0)
1918
sewardjf5c1a7f2006-10-17 01:32:48 +00001919#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +00001920
sewardjf5c1a7f2006-10-17 01:32:48 +00001921/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00001922
sewardjf5c1a7f2006-10-17 01:32:48 +00001923#if defined(PLAT_ppc64_linux)
sewardj9734b202006-01-17 01:49:37 +00001924
1925/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1926
1927/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00001928#define __CALLER_SAVED_REGS \
1929 "lr", "ctr", "xer", \
1930 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1931 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1932 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00001933
1934/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
1935 long) == 8. */
1936
sewardjd68ac3e2006-01-20 14:31:57 +00001937#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00001938 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001939 volatile OrigFn _orig = (orig); \
1940 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00001941 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001942 /* _argvec[0] holds current r2 across the call */ \
1943 _argvec[1] = (unsigned long)_orig.r2; \
1944 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00001945 __asm__ volatile( \
1946 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001947 "std 2,-16(11)\n\t" /* save tocptr */ \
1948 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1949 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00001950 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1951 "mr 11,%1\n\t" \
1952 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001953 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00001954 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00001955 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00001956 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1957 ); \
1958 lval = (__typeof__(lval)) _res; \
1959 } while (0)
1960
sewardjd68ac3e2006-01-20 14:31:57 +00001961#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00001962 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001963 volatile OrigFn _orig = (orig); \
1964 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00001965 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001966 /* _argvec[0] holds current r2 across the call */ \
1967 _argvec[1] = (unsigned long)_orig.r2; \
1968 _argvec[2] = (unsigned long)_orig.nraddr; \
1969 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00001970 __asm__ volatile( \
1971 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001972 "std 2,-16(11)\n\t" /* save tocptr */ \
1973 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1974 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1975 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00001976 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1977 "mr 11,%1\n\t" \
1978 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001979 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00001980 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00001981 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00001982 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1983 ); \
1984 lval = (__typeof__(lval)) _res; \
1985 } while (0)
1986
sewardjd68ac3e2006-01-20 14:31:57 +00001987#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00001988 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001989 volatile OrigFn _orig = (orig); \
1990 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00001991 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001992 /* _argvec[0] holds current r2 across the call */ \
1993 _argvec[1] = (unsigned long)_orig.r2; \
1994 _argvec[2] = (unsigned long)_orig.nraddr; \
1995 _argvec[2+1] = (unsigned long)arg1; \
1996 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00001997 __asm__ volatile( \
1998 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00001999 "std 2,-16(11)\n\t" /* save tocptr */ \
2000 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2001 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00002002 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00002003 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002004 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2005 "mr 11,%1\n\t" \
2006 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002007 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002008 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002009 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002010 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2011 ); \
2012 lval = (__typeof__(lval)) _res; \
2013 } while (0)
2014
sewardjcd636392006-03-12 16:48:14 +00002015#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2016 do { \
2017 volatile OrigFn _orig = (orig); \
2018 volatile unsigned long _argvec[3+3]; \
2019 volatile unsigned long _res; \
2020 /* _argvec[0] holds current r2 across the call */ \
2021 _argvec[1] = (unsigned long)_orig.r2; \
2022 _argvec[2] = (unsigned long)_orig.nraddr; \
2023 _argvec[2+1] = (unsigned long)arg1; \
2024 _argvec[2+2] = (unsigned long)arg2; \
2025 _argvec[2+3] = (unsigned long)arg3; \
2026 __asm__ volatile( \
2027 "mr 11,%1\n\t" \
2028 "std 2,-16(11)\n\t" /* save tocptr */ \
2029 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2030 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2031 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2032 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2033 "ld 11, 0(11)\n\t" /* target->r11 */ \
2034 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2035 "mr 11,%1\n\t" \
2036 "mr %0,3\n\t" \
2037 "ld 2,-16(11)" /* restore tocptr */ \
2038 : /*out*/ "=r" (_res) \
2039 : /*in*/ "r" (&_argvec[2]) \
2040 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2041 ); \
2042 lval = (__typeof__(lval)) _res; \
2043 } while (0)
2044
2045#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2046 do { \
2047 volatile OrigFn _orig = (orig); \
2048 volatile unsigned long _argvec[3+4]; \
2049 volatile unsigned long _res; \
2050 /* _argvec[0] holds current r2 across the call */ \
2051 _argvec[1] = (unsigned long)_orig.r2; \
2052 _argvec[2] = (unsigned long)_orig.nraddr; \
2053 _argvec[2+1] = (unsigned long)arg1; \
2054 _argvec[2+2] = (unsigned long)arg2; \
2055 _argvec[2+3] = (unsigned long)arg3; \
2056 _argvec[2+4] = (unsigned long)arg4; \
2057 __asm__ volatile( \
2058 "mr 11,%1\n\t" \
2059 "std 2,-16(11)\n\t" /* save tocptr */ \
2060 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2061 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2062 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2063 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2064 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2065 "ld 11, 0(11)\n\t" /* target->r11 */ \
2066 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2067 "mr 11,%1\n\t" \
2068 "mr %0,3\n\t" \
2069 "ld 2,-16(11)" /* restore tocptr */ \
2070 : /*out*/ "=r" (_res) \
2071 : /*in*/ "r" (&_argvec[2]) \
2072 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2073 ); \
2074 lval = (__typeof__(lval)) _res; \
2075 } while (0)
2076
2077#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2078 do { \
2079 volatile OrigFn _orig = (orig); \
2080 volatile unsigned long _argvec[3+5]; \
2081 volatile unsigned long _res; \
2082 /* _argvec[0] holds current r2 across the call */ \
2083 _argvec[1] = (unsigned long)_orig.r2; \
2084 _argvec[2] = (unsigned long)_orig.nraddr; \
2085 _argvec[2+1] = (unsigned long)arg1; \
2086 _argvec[2+2] = (unsigned long)arg2; \
2087 _argvec[2+3] = (unsigned long)arg3; \
2088 _argvec[2+4] = (unsigned long)arg4; \
2089 _argvec[2+5] = (unsigned long)arg5; \
2090 __asm__ volatile( \
2091 "mr 11,%1\n\t" \
2092 "std 2,-16(11)\n\t" /* save tocptr */ \
2093 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2094 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2095 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2096 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2097 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2098 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2099 "ld 11, 0(11)\n\t" /* target->r11 */ \
2100 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2101 "mr 11,%1\n\t" \
2102 "mr %0,3\n\t" \
2103 "ld 2,-16(11)" /* restore tocptr */ \
2104 : /*out*/ "=r" (_res) \
2105 : /*in*/ "r" (&_argvec[2]) \
2106 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2107 ); \
2108 lval = (__typeof__(lval)) _res; \
2109 } while (0)
2110
2111#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2112 do { \
2113 volatile OrigFn _orig = (orig); \
2114 volatile unsigned long _argvec[3+6]; \
2115 volatile unsigned long _res; \
2116 /* _argvec[0] holds current r2 across the call */ \
2117 _argvec[1] = (unsigned long)_orig.r2; \
2118 _argvec[2] = (unsigned long)_orig.nraddr; \
2119 _argvec[2+1] = (unsigned long)arg1; \
2120 _argvec[2+2] = (unsigned long)arg2; \
2121 _argvec[2+3] = (unsigned long)arg3; \
2122 _argvec[2+4] = (unsigned long)arg4; \
2123 _argvec[2+5] = (unsigned long)arg5; \
2124 _argvec[2+6] = (unsigned long)arg6; \
2125 __asm__ volatile( \
2126 "mr 11,%1\n\t" \
2127 "std 2,-16(11)\n\t" /* save tocptr */ \
2128 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2129 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2130 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2131 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2132 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2133 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2134 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2135 "ld 11, 0(11)\n\t" /* target->r11 */ \
2136 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2137 "mr 11,%1\n\t" \
2138 "mr %0,3\n\t" \
2139 "ld 2,-16(11)" /* restore tocptr */ \
2140 : /*out*/ "=r" (_res) \
2141 : /*in*/ "r" (&_argvec[2]) \
2142 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2143 ); \
2144 lval = (__typeof__(lval)) _res; \
2145 } while (0)
2146
2147#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2148 arg7) \
2149 do { \
2150 volatile OrigFn _orig = (orig); \
2151 volatile unsigned long _argvec[3+7]; \
2152 volatile unsigned long _res; \
2153 /* _argvec[0] holds current r2 across the call */ \
2154 _argvec[1] = (unsigned long)_orig.r2; \
2155 _argvec[2] = (unsigned long)_orig.nraddr; \
2156 _argvec[2+1] = (unsigned long)arg1; \
2157 _argvec[2+2] = (unsigned long)arg2; \
2158 _argvec[2+3] = (unsigned long)arg3; \
2159 _argvec[2+4] = (unsigned long)arg4; \
2160 _argvec[2+5] = (unsigned long)arg5; \
2161 _argvec[2+6] = (unsigned long)arg6; \
2162 _argvec[2+7] = (unsigned long)arg7; \
2163 __asm__ volatile( \
2164 "mr 11,%1\n\t" \
2165 "std 2,-16(11)\n\t" /* save tocptr */ \
2166 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2167 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2168 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2169 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2170 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2171 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2172 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2173 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2174 "ld 11, 0(11)\n\t" /* target->r11 */ \
2175 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2176 "mr 11,%1\n\t" \
2177 "mr %0,3\n\t" \
2178 "ld 2,-16(11)" /* restore tocptr */ \
2179 : /*out*/ "=r" (_res) \
2180 : /*in*/ "r" (&_argvec[2]) \
2181 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2182 ); \
2183 lval = (__typeof__(lval)) _res; \
2184 } while (0)
2185
2186#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2187 arg7,arg8) \
2188 do { \
2189 volatile OrigFn _orig = (orig); \
2190 volatile unsigned long _argvec[3+8]; \
2191 volatile unsigned long _res; \
2192 /* _argvec[0] holds current r2 across the call */ \
2193 _argvec[1] = (unsigned long)_orig.r2; \
2194 _argvec[2] = (unsigned long)_orig.nraddr; \
2195 _argvec[2+1] = (unsigned long)arg1; \
2196 _argvec[2+2] = (unsigned long)arg2; \
2197 _argvec[2+3] = (unsigned long)arg3; \
2198 _argvec[2+4] = (unsigned long)arg4; \
2199 _argvec[2+5] = (unsigned long)arg5; \
2200 _argvec[2+6] = (unsigned long)arg6; \
2201 _argvec[2+7] = (unsigned long)arg7; \
2202 _argvec[2+8] = (unsigned long)arg8; \
2203 __asm__ volatile( \
2204 "mr 11,%1\n\t" \
2205 "std 2,-16(11)\n\t" /* save tocptr */ \
2206 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2207 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2208 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2209 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2210 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2211 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2212 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2213 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2214 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2215 "ld 11, 0(11)\n\t" /* target->r11 */ \
2216 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2217 "mr 11,%1\n\t" \
2218 "mr %0,3\n\t" \
2219 "ld 2,-16(11)" /* restore tocptr */ \
2220 : /*out*/ "=r" (_res) \
2221 : /*in*/ "r" (&_argvec[2]) \
2222 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2223 ); \
2224 lval = (__typeof__(lval)) _res; \
2225 } while (0)
2226
2227#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2228 arg7,arg8,arg9) \
2229 do { \
2230 volatile OrigFn _orig = (orig); \
2231 volatile unsigned long _argvec[3+9]; \
2232 volatile unsigned long _res; \
2233 /* _argvec[0] holds current r2 across the call */ \
2234 _argvec[1] = (unsigned long)_orig.r2; \
2235 _argvec[2] = (unsigned long)_orig.nraddr; \
2236 _argvec[2+1] = (unsigned long)arg1; \
2237 _argvec[2+2] = (unsigned long)arg2; \
2238 _argvec[2+3] = (unsigned long)arg3; \
2239 _argvec[2+4] = (unsigned long)arg4; \
2240 _argvec[2+5] = (unsigned long)arg5; \
2241 _argvec[2+6] = (unsigned long)arg6; \
2242 _argvec[2+7] = (unsigned long)arg7; \
2243 _argvec[2+8] = (unsigned long)arg8; \
2244 _argvec[2+9] = (unsigned long)arg9; \
2245 __asm__ volatile( \
2246 "mr 11,%1\n\t" \
2247 "std 2,-16(11)\n\t" /* save tocptr */ \
2248 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2249 "addi 1,1,-128\n\t" /* expand stack frame */ \
2250 /* arg9 */ \
2251 "ld 3,72(11)\n\t" \
2252 "std 3,112(1)\n\t" \
2253 /* args1-8 */ \
2254 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2255 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2256 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2257 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2258 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2259 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2260 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2261 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2262 "ld 11, 0(11)\n\t" /* target->r11 */ \
2263 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2264 "mr 11,%1\n\t" \
2265 "mr %0,3\n\t" \
2266 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2267 "addi 1,1,128" /* restore frame */ \
2268 : /*out*/ "=r" (_res) \
2269 : /*in*/ "r" (&_argvec[2]) \
2270 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2271 ); \
2272 lval = (__typeof__(lval)) _res; \
2273 } while (0)
2274
2275#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2276 arg7,arg8,arg9,arg10) \
2277 do { \
2278 volatile OrigFn _orig = (orig); \
2279 volatile unsigned long _argvec[3+10]; \
2280 volatile unsigned long _res; \
2281 /* _argvec[0] holds current r2 across the call */ \
2282 _argvec[1] = (unsigned long)_orig.r2; \
2283 _argvec[2] = (unsigned long)_orig.nraddr; \
2284 _argvec[2+1] = (unsigned long)arg1; \
2285 _argvec[2+2] = (unsigned long)arg2; \
2286 _argvec[2+3] = (unsigned long)arg3; \
2287 _argvec[2+4] = (unsigned long)arg4; \
2288 _argvec[2+5] = (unsigned long)arg5; \
2289 _argvec[2+6] = (unsigned long)arg6; \
2290 _argvec[2+7] = (unsigned long)arg7; \
2291 _argvec[2+8] = (unsigned long)arg8; \
2292 _argvec[2+9] = (unsigned long)arg9; \
2293 _argvec[2+10] = (unsigned long)arg10; \
2294 __asm__ volatile( \
2295 "mr 11,%1\n\t" \
2296 "std 2,-16(11)\n\t" /* save tocptr */ \
2297 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2298 "addi 1,1,-128\n\t" /* expand stack frame */ \
2299 /* arg10 */ \
2300 "ld 3,80(11)\n\t" \
2301 "std 3,120(1)\n\t" \
2302 /* arg9 */ \
2303 "ld 3,72(11)\n\t" \
2304 "std 3,112(1)\n\t" \
2305 /* args1-8 */ \
2306 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2307 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2308 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2309 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2310 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2311 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2312 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2313 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2314 "ld 11, 0(11)\n\t" /* target->r11 */ \
2315 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2316 "mr 11,%1\n\t" \
2317 "mr %0,3\n\t" \
2318 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2319 "addi 1,1,128" /* restore frame */ \
2320 : /*out*/ "=r" (_res) \
2321 : /*in*/ "r" (&_argvec[2]) \
2322 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2323 ); \
2324 lval = (__typeof__(lval)) _res; \
2325 } while (0)
2326
2327#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2328 arg7,arg8,arg9,arg10,arg11) \
2329 do { \
2330 volatile OrigFn _orig = (orig); \
2331 volatile unsigned long _argvec[3+11]; \
2332 volatile unsigned long _res; \
2333 /* _argvec[0] holds current r2 across the call */ \
2334 _argvec[1] = (unsigned long)_orig.r2; \
2335 _argvec[2] = (unsigned long)_orig.nraddr; \
2336 _argvec[2+1] = (unsigned long)arg1; \
2337 _argvec[2+2] = (unsigned long)arg2; \
2338 _argvec[2+3] = (unsigned long)arg3; \
2339 _argvec[2+4] = (unsigned long)arg4; \
2340 _argvec[2+5] = (unsigned long)arg5; \
2341 _argvec[2+6] = (unsigned long)arg6; \
2342 _argvec[2+7] = (unsigned long)arg7; \
2343 _argvec[2+8] = (unsigned long)arg8; \
2344 _argvec[2+9] = (unsigned long)arg9; \
2345 _argvec[2+10] = (unsigned long)arg10; \
2346 _argvec[2+11] = (unsigned long)arg11; \
2347 __asm__ volatile( \
2348 "mr 11,%1\n\t" \
2349 "std 2,-16(11)\n\t" /* save tocptr */ \
2350 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2351 "addi 1,1,-144\n\t" /* expand stack frame */ \
2352 /* arg11 */ \
2353 "ld 3,88(11)\n\t" \
2354 "std 3,128(1)\n\t" \
2355 /* arg10 */ \
2356 "ld 3,80(11)\n\t" \
2357 "std 3,120(1)\n\t" \
2358 /* arg9 */ \
2359 "ld 3,72(11)\n\t" \
2360 "std 3,112(1)\n\t" \
2361 /* args1-8 */ \
2362 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2363 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2364 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2365 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2366 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2367 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2368 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2369 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2370 "ld 11, 0(11)\n\t" /* target->r11 */ \
2371 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2372 "mr 11,%1\n\t" \
2373 "mr %0,3\n\t" \
2374 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2375 "addi 1,1,144" /* restore frame */ \
2376 : /*out*/ "=r" (_res) \
2377 : /*in*/ "r" (&_argvec[2]) \
2378 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2379 ); \
2380 lval = (__typeof__(lval)) _res; \
2381 } while (0)
2382
2383#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2384 arg7,arg8,arg9,arg10,arg11,arg12) \
2385 do { \
2386 volatile OrigFn _orig = (orig); \
2387 volatile unsigned long _argvec[3+12]; \
2388 volatile unsigned long _res; \
2389 /* _argvec[0] holds current r2 across the call */ \
2390 _argvec[1] = (unsigned long)_orig.r2; \
2391 _argvec[2] = (unsigned long)_orig.nraddr; \
2392 _argvec[2+1] = (unsigned long)arg1; \
2393 _argvec[2+2] = (unsigned long)arg2; \
2394 _argvec[2+3] = (unsigned long)arg3; \
2395 _argvec[2+4] = (unsigned long)arg4; \
2396 _argvec[2+5] = (unsigned long)arg5; \
2397 _argvec[2+6] = (unsigned long)arg6; \
2398 _argvec[2+7] = (unsigned long)arg7; \
2399 _argvec[2+8] = (unsigned long)arg8; \
2400 _argvec[2+9] = (unsigned long)arg9; \
2401 _argvec[2+10] = (unsigned long)arg10; \
2402 _argvec[2+11] = (unsigned long)arg11; \
2403 _argvec[2+12] = (unsigned long)arg12; \
2404 __asm__ volatile( \
2405 "mr 11,%1\n\t" \
2406 "std 2,-16(11)\n\t" /* save tocptr */ \
2407 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2408 "addi 1,1,-144\n\t" /* expand stack frame */ \
2409 /* arg12 */ \
2410 "ld 3,96(11)\n\t" \
2411 "std 3,136(1)\n\t" \
2412 /* arg11 */ \
2413 "ld 3,88(11)\n\t" \
2414 "std 3,128(1)\n\t" \
2415 /* arg10 */ \
2416 "ld 3,80(11)\n\t" \
2417 "std 3,120(1)\n\t" \
2418 /* arg9 */ \
2419 "ld 3,72(11)\n\t" \
2420 "std 3,112(1)\n\t" \
2421 /* args1-8 */ \
2422 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2423 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2424 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2425 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2426 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2427 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2428 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2429 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2430 "ld 11, 0(11)\n\t" /* target->r11 */ \
2431 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2432 "mr 11,%1\n\t" \
2433 "mr %0,3\n\t" \
2434 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2435 "addi 1,1,144" /* restore frame */ \
2436 : /*out*/ "=r" (_res) \
2437 : /*in*/ "r" (&_argvec[2]) \
2438 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2439 ); \
2440 lval = (__typeof__(lval)) _res; \
2441 } while (0)
2442
sewardjf5c1a7f2006-10-17 01:32:48 +00002443#endif /* PLAT_ppc64_linux */
2444
2445/* ------------------------ ppc32-aix5 ------------------------- */
2446
2447#if defined(PLAT_ppc32_aix5)
2448
2449/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2450
2451/* These regs are trashed by the hidden call. */
2452#define __CALLER_SAVED_REGS \
2453 "lr", "ctr", "xer", \
2454 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2455 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2456 "r11", "r12", "r13"
2457
2458/* Expand the stack frame, copying enough info that unwinding
2459 still works. Trashes r3. */
2460
2461#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
2462 "addi 1,1,-" #_n_fr "\n\t" \
2463 "lwz 3," #_n_fr "(1)\n\t" \
2464 "stw 3,0(1)\n\t"
2465
2466#define VG_CONTRACT_FRAME_BY(_n_fr) \
2467 "addi 1,1," #_n_fr "\n\t"
2468
2469/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
2470 long) == 4. */
2471
2472#define CALL_FN_W_v(lval, orig) \
2473 do { \
2474 volatile OrigFn _orig = (orig); \
2475 volatile unsigned long _argvec[3+0]; \
2476 volatile unsigned long _res; \
2477 /* _argvec[0] holds current r2 across the call */ \
2478 _argvec[1] = (unsigned long)_orig.r2; \
2479 _argvec[2] = (unsigned long)_orig.nraddr; \
2480 __asm__ volatile( \
2481 "mr 11,%1\n\t" \
2482 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2483 "stw 2,-8(11)\n\t" /* save tocptr */ \
2484 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2485 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2486 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2487 "mr 11,%1\n\t" \
2488 "mr %0,3\n\t" \
2489 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2490 VG_CONTRACT_FRAME_BY(512) \
2491 : /*out*/ "=r" (_res) \
2492 : /*in*/ "r" (&_argvec[2]) \
2493 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2494 ); \
2495 lval = (__typeof__(lval)) _res; \
2496 } while (0)
2497
2498#define CALL_FN_W_W(lval, orig, arg1) \
2499 do { \
2500 volatile OrigFn _orig = (orig); \
2501 volatile unsigned long _argvec[3+1]; \
2502 volatile unsigned long _res; \
2503 /* _argvec[0] holds current r2 across the call */ \
2504 _argvec[1] = (unsigned long)_orig.r2; \
2505 _argvec[2] = (unsigned long)_orig.nraddr; \
2506 _argvec[2+1] = (unsigned long)arg1; \
2507 __asm__ volatile( \
2508 "mr 11,%1\n\t" \
2509 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2510 "stw 2,-8(11)\n\t" /* save tocptr */ \
2511 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2512 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2513 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2514 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2515 "mr 11,%1\n\t" \
2516 "mr %0,3\n\t" \
2517 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2518 VG_CONTRACT_FRAME_BY(512) \
2519 : /*out*/ "=r" (_res) \
2520 : /*in*/ "r" (&_argvec[2]) \
2521 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2522 ); \
2523 lval = (__typeof__(lval)) _res; \
2524 } while (0)
2525
2526#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2527 do { \
2528 volatile OrigFn _orig = (orig); \
2529 volatile unsigned long _argvec[3+2]; \
2530 volatile unsigned long _res; \
2531 /* _argvec[0] holds current r2 across the call */ \
2532 _argvec[1] = (unsigned long)_orig.r2; \
2533 _argvec[2] = (unsigned long)_orig.nraddr; \
2534 _argvec[2+1] = (unsigned long)arg1; \
2535 _argvec[2+2] = (unsigned long)arg2; \
2536 __asm__ volatile( \
2537 "mr 11,%1\n\t" \
2538 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2539 "stw 2,-8(11)\n\t" /* save tocptr */ \
2540 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2541 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2542 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2543 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2544 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2545 "mr 11,%1\n\t" \
2546 "mr %0,3\n\t" \
2547 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2548 VG_CONTRACT_FRAME_BY(512) \
2549 : /*out*/ "=r" (_res) \
2550 : /*in*/ "r" (&_argvec[2]) \
2551 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2552 ); \
2553 lval = (__typeof__(lval)) _res; \
2554 } while (0)
2555
2556#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2557 do { \
2558 volatile OrigFn _orig = (orig); \
2559 volatile unsigned long _argvec[3+3]; \
2560 volatile unsigned long _res; \
2561 /* _argvec[0] holds current r2 across the call */ \
2562 _argvec[1] = (unsigned long)_orig.r2; \
2563 _argvec[2] = (unsigned long)_orig.nraddr; \
2564 _argvec[2+1] = (unsigned long)arg1; \
2565 _argvec[2+2] = (unsigned long)arg2; \
2566 _argvec[2+3] = (unsigned long)arg3; \
2567 __asm__ volatile( \
2568 "mr 11,%1\n\t" \
2569 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2570 "stw 2,-8(11)\n\t" /* save tocptr */ \
2571 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2572 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2573 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2574 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2575 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2576 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2577 "mr 11,%1\n\t" \
2578 "mr %0,3\n\t" \
2579 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2580 VG_CONTRACT_FRAME_BY(512) \
2581 : /*out*/ "=r" (_res) \
2582 : /*in*/ "r" (&_argvec[2]) \
2583 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2584 ); \
2585 lval = (__typeof__(lval)) _res; \
2586 } while (0)
2587
2588#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2589 do { \
2590 volatile OrigFn _orig = (orig); \
2591 volatile unsigned long _argvec[3+4]; \
2592 volatile unsigned long _res; \
2593 /* _argvec[0] holds current r2 across the call */ \
2594 _argvec[1] = (unsigned long)_orig.r2; \
2595 _argvec[2] = (unsigned long)_orig.nraddr; \
2596 _argvec[2+1] = (unsigned long)arg1; \
2597 _argvec[2+2] = (unsigned long)arg2; \
2598 _argvec[2+3] = (unsigned long)arg3; \
2599 _argvec[2+4] = (unsigned long)arg4; \
2600 __asm__ volatile( \
2601 "mr 11,%1\n\t" \
2602 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2603 "stw 2,-8(11)\n\t" /* save tocptr */ \
2604 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2605 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2606 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2607 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2608 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2609 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2610 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2611 "mr 11,%1\n\t" \
2612 "mr %0,3\n\t" \
2613 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2614 VG_CONTRACT_FRAME_BY(512) \
2615 : /*out*/ "=r" (_res) \
2616 : /*in*/ "r" (&_argvec[2]) \
2617 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2618 ); \
2619 lval = (__typeof__(lval)) _res; \
2620 } while (0)
2621
2622#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2623 do { \
2624 volatile OrigFn _orig = (orig); \
2625 volatile unsigned long _argvec[3+5]; \
2626 volatile unsigned long _res; \
2627 /* _argvec[0] holds current r2 across the call */ \
2628 _argvec[1] = (unsigned long)_orig.r2; \
2629 _argvec[2] = (unsigned long)_orig.nraddr; \
2630 _argvec[2+1] = (unsigned long)arg1; \
2631 _argvec[2+2] = (unsigned long)arg2; \
2632 _argvec[2+3] = (unsigned long)arg3; \
2633 _argvec[2+4] = (unsigned long)arg4; \
2634 _argvec[2+5] = (unsigned long)arg5; \
2635 __asm__ volatile( \
2636 "mr 11,%1\n\t" \
2637 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2638 "stw 2,-8(11)\n\t" /* save tocptr */ \
2639 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2640 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2641 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2642 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2643 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2644 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2645 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2646 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2647 "mr 11,%1\n\t" \
2648 "mr %0,3\n\t" \
2649 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2650 VG_CONTRACT_FRAME_BY(512) \
2651 : /*out*/ "=r" (_res) \
2652 : /*in*/ "r" (&_argvec[2]) \
2653 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2654 ); \
2655 lval = (__typeof__(lval)) _res; \
2656 } while (0)
2657
2658#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2659 do { \
2660 volatile OrigFn _orig = (orig); \
2661 volatile unsigned long _argvec[3+6]; \
2662 volatile unsigned long _res; \
2663 /* _argvec[0] holds current r2 across the call */ \
2664 _argvec[1] = (unsigned long)_orig.r2; \
2665 _argvec[2] = (unsigned long)_orig.nraddr; \
2666 _argvec[2+1] = (unsigned long)arg1; \
2667 _argvec[2+2] = (unsigned long)arg2; \
2668 _argvec[2+3] = (unsigned long)arg3; \
2669 _argvec[2+4] = (unsigned long)arg4; \
2670 _argvec[2+5] = (unsigned long)arg5; \
2671 _argvec[2+6] = (unsigned long)arg6; \
2672 __asm__ volatile( \
2673 "mr 11,%1\n\t" \
2674 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2675 "stw 2,-8(11)\n\t" /* save tocptr */ \
2676 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2677 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2678 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2679 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2680 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2681 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2682 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2683 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2684 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2685 "mr 11,%1\n\t" \
2686 "mr %0,3\n\t" \
2687 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2688 VG_CONTRACT_FRAME_BY(512) \
2689 : /*out*/ "=r" (_res) \
2690 : /*in*/ "r" (&_argvec[2]) \
2691 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2692 ); \
2693 lval = (__typeof__(lval)) _res; \
2694 } while (0)
2695
2696#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2697 arg7) \
2698 do { \
2699 volatile OrigFn _orig = (orig); \
2700 volatile unsigned long _argvec[3+7]; \
2701 volatile unsigned long _res; \
2702 /* _argvec[0] holds current r2 across the call */ \
2703 _argvec[1] = (unsigned long)_orig.r2; \
2704 _argvec[2] = (unsigned long)_orig.nraddr; \
2705 _argvec[2+1] = (unsigned long)arg1; \
2706 _argvec[2+2] = (unsigned long)arg2; \
2707 _argvec[2+3] = (unsigned long)arg3; \
2708 _argvec[2+4] = (unsigned long)arg4; \
2709 _argvec[2+5] = (unsigned long)arg5; \
2710 _argvec[2+6] = (unsigned long)arg6; \
2711 _argvec[2+7] = (unsigned long)arg7; \
2712 __asm__ volatile( \
2713 "mr 11,%1\n\t" \
2714 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2715 "stw 2,-8(11)\n\t" /* save tocptr */ \
2716 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2717 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2718 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2719 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2720 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2721 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2722 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2723 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2724 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2725 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2726 "mr 11,%1\n\t" \
2727 "mr %0,3\n\t" \
2728 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2729 VG_CONTRACT_FRAME_BY(512) \
2730 : /*out*/ "=r" (_res) \
2731 : /*in*/ "r" (&_argvec[2]) \
2732 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2733 ); \
2734 lval = (__typeof__(lval)) _res; \
2735 } while (0)
2736
2737#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2738 arg7,arg8) \
2739 do { \
2740 volatile OrigFn _orig = (orig); \
2741 volatile unsigned long _argvec[3+8]; \
2742 volatile unsigned long _res; \
2743 /* _argvec[0] holds current r2 across the call */ \
2744 _argvec[1] = (unsigned long)_orig.r2; \
2745 _argvec[2] = (unsigned long)_orig.nraddr; \
2746 _argvec[2+1] = (unsigned long)arg1; \
2747 _argvec[2+2] = (unsigned long)arg2; \
2748 _argvec[2+3] = (unsigned long)arg3; \
2749 _argvec[2+4] = (unsigned long)arg4; \
2750 _argvec[2+5] = (unsigned long)arg5; \
2751 _argvec[2+6] = (unsigned long)arg6; \
2752 _argvec[2+7] = (unsigned long)arg7; \
2753 _argvec[2+8] = (unsigned long)arg8; \
2754 __asm__ volatile( \
2755 "mr 11,%1\n\t" \
2756 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2757 "stw 2,-8(11)\n\t" /* save tocptr */ \
2758 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2759 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2760 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2761 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2762 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2763 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2764 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2765 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2766 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2767 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2768 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2769 "mr 11,%1\n\t" \
2770 "mr %0,3\n\t" \
2771 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2772 VG_CONTRACT_FRAME_BY(512) \
2773 : /*out*/ "=r" (_res) \
2774 : /*in*/ "r" (&_argvec[2]) \
2775 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2776 ); \
2777 lval = (__typeof__(lval)) _res; \
2778 } while (0)
2779
2780#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2781 arg7,arg8,arg9) \
2782 do { \
2783 volatile OrigFn _orig = (orig); \
2784 volatile unsigned long _argvec[3+9]; \
2785 volatile unsigned long _res; \
2786 /* _argvec[0] holds current r2 across the call */ \
2787 _argvec[1] = (unsigned long)_orig.r2; \
2788 _argvec[2] = (unsigned long)_orig.nraddr; \
2789 _argvec[2+1] = (unsigned long)arg1; \
2790 _argvec[2+2] = (unsigned long)arg2; \
2791 _argvec[2+3] = (unsigned long)arg3; \
2792 _argvec[2+4] = (unsigned long)arg4; \
2793 _argvec[2+5] = (unsigned long)arg5; \
2794 _argvec[2+6] = (unsigned long)arg6; \
2795 _argvec[2+7] = (unsigned long)arg7; \
2796 _argvec[2+8] = (unsigned long)arg8; \
2797 _argvec[2+9] = (unsigned long)arg9; \
2798 __asm__ volatile( \
2799 "mr 11,%1\n\t" \
2800 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2801 "stw 2,-8(11)\n\t" /* save tocptr */ \
2802 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2803 VG_EXPAND_FRAME_BY_trashes_r3(64) \
2804 /* arg9 */ \
2805 "lwz 3,36(11)\n\t" \
2806 "stw 3,56(1)\n\t" \
2807 /* args1-8 */ \
2808 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2809 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2810 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2811 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2812 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2813 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2814 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2815 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2816 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2817 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2818 "mr 11,%1\n\t" \
2819 "mr %0,3\n\t" \
2820 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2821 VG_CONTRACT_FRAME_BY(64) \
2822 VG_CONTRACT_FRAME_BY(512) \
2823 : /*out*/ "=r" (_res) \
2824 : /*in*/ "r" (&_argvec[2]) \
2825 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2826 ); \
2827 lval = (__typeof__(lval)) _res; \
2828 } while (0)
2829
2830#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2831 arg7,arg8,arg9,arg10) \
2832 do { \
2833 volatile OrigFn _orig = (orig); \
2834 volatile unsigned long _argvec[3+10]; \
2835 volatile unsigned long _res; \
2836 /* _argvec[0] holds current r2 across the call */ \
2837 _argvec[1] = (unsigned long)_orig.r2; \
2838 _argvec[2] = (unsigned long)_orig.nraddr; \
2839 _argvec[2+1] = (unsigned long)arg1; \
2840 _argvec[2+2] = (unsigned long)arg2; \
2841 _argvec[2+3] = (unsigned long)arg3; \
2842 _argvec[2+4] = (unsigned long)arg4; \
2843 _argvec[2+5] = (unsigned long)arg5; \
2844 _argvec[2+6] = (unsigned long)arg6; \
2845 _argvec[2+7] = (unsigned long)arg7; \
2846 _argvec[2+8] = (unsigned long)arg8; \
2847 _argvec[2+9] = (unsigned long)arg9; \
2848 _argvec[2+10] = (unsigned long)arg10; \
2849 __asm__ volatile( \
2850 "mr 11,%1\n\t" \
2851 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2852 "stw 2,-8(11)\n\t" /* save tocptr */ \
2853 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2854 VG_EXPAND_FRAME_BY_trashes_r3(64) \
2855 /* arg10 */ \
2856 "lwz 3,40(11)\n\t" \
2857 "stw 3,60(1)\n\t" \
2858 /* arg9 */ \
2859 "lwz 3,36(11)\n\t" \
2860 "stw 3,56(1)\n\t" \
2861 /* args1-8 */ \
2862 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2863 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2864 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2865 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2866 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2867 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2868 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2869 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2870 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2871 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2872 "mr 11,%1\n\t" \
2873 "mr %0,3\n\t" \
2874 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2875 VG_CONTRACT_FRAME_BY(64) \
2876 VG_CONTRACT_FRAME_BY(512) \
2877 : /*out*/ "=r" (_res) \
2878 : /*in*/ "r" (&_argvec[2]) \
2879 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2880 ); \
2881 lval = (__typeof__(lval)) _res; \
2882 } while (0)
2883
2884#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2885 arg7,arg8,arg9,arg10,arg11) \
2886 do { \
2887 volatile OrigFn _orig = (orig); \
2888 volatile unsigned long _argvec[3+11]; \
2889 volatile unsigned long _res; \
2890 /* _argvec[0] holds current r2 across the call */ \
2891 _argvec[1] = (unsigned long)_orig.r2; \
2892 _argvec[2] = (unsigned long)_orig.nraddr; \
2893 _argvec[2+1] = (unsigned long)arg1; \
2894 _argvec[2+2] = (unsigned long)arg2; \
2895 _argvec[2+3] = (unsigned long)arg3; \
2896 _argvec[2+4] = (unsigned long)arg4; \
2897 _argvec[2+5] = (unsigned long)arg5; \
2898 _argvec[2+6] = (unsigned long)arg6; \
2899 _argvec[2+7] = (unsigned long)arg7; \
2900 _argvec[2+8] = (unsigned long)arg8; \
2901 _argvec[2+9] = (unsigned long)arg9; \
2902 _argvec[2+10] = (unsigned long)arg10; \
2903 _argvec[2+11] = (unsigned long)arg11; \
2904 __asm__ volatile( \
2905 "mr 11,%1\n\t" \
2906 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2907 "stw 2,-8(11)\n\t" /* save tocptr */ \
2908 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2909 VG_EXPAND_FRAME_BY_trashes_r3(72) \
2910 /* arg11 */ \
2911 "lwz 3,44(11)\n\t" \
2912 "stw 3,64(1)\n\t" \
2913 /* arg10 */ \
2914 "lwz 3,40(11)\n\t" \
2915 "stw 3,60(1)\n\t" \
2916 /* arg9 */ \
2917 "lwz 3,36(11)\n\t" \
2918 "stw 3,56(1)\n\t" \
2919 /* args1-8 */ \
2920 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2921 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2922 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2923 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2924 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2925 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2926 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2927 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2928 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2929 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2930 "mr 11,%1\n\t" \
2931 "mr %0,3\n\t" \
2932 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2933 VG_CONTRACT_FRAME_BY(72) \
2934 VG_CONTRACT_FRAME_BY(512) \
2935 : /*out*/ "=r" (_res) \
2936 : /*in*/ "r" (&_argvec[2]) \
2937 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2938 ); \
2939 lval = (__typeof__(lval)) _res; \
2940 } while (0)
2941
2942#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2943 arg7,arg8,arg9,arg10,arg11,arg12) \
2944 do { \
2945 volatile OrigFn _orig = (orig); \
2946 volatile unsigned long _argvec[3+12]; \
2947 volatile unsigned long _res; \
2948 /* _argvec[0] holds current r2 across the call */ \
2949 _argvec[1] = (unsigned long)_orig.r2; \
2950 _argvec[2] = (unsigned long)_orig.nraddr; \
2951 _argvec[2+1] = (unsigned long)arg1; \
2952 _argvec[2+2] = (unsigned long)arg2; \
2953 _argvec[2+3] = (unsigned long)arg3; \
2954 _argvec[2+4] = (unsigned long)arg4; \
2955 _argvec[2+5] = (unsigned long)arg5; \
2956 _argvec[2+6] = (unsigned long)arg6; \
2957 _argvec[2+7] = (unsigned long)arg7; \
2958 _argvec[2+8] = (unsigned long)arg8; \
2959 _argvec[2+9] = (unsigned long)arg9; \
2960 _argvec[2+10] = (unsigned long)arg10; \
2961 _argvec[2+11] = (unsigned long)arg11; \
2962 _argvec[2+12] = (unsigned long)arg12; \
2963 __asm__ volatile( \
2964 "mr 11,%1\n\t" \
2965 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2966 "stw 2,-8(11)\n\t" /* save tocptr */ \
2967 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2968 VG_EXPAND_FRAME_BY_trashes_r3(72) \
2969 /* arg12 */ \
2970 "lwz 3,48(11)\n\t" \
2971 "stw 3,68(1)\n\t" \
2972 /* arg11 */ \
2973 "lwz 3,44(11)\n\t" \
2974 "stw 3,64(1)\n\t" \
2975 /* arg10 */ \
2976 "lwz 3,40(11)\n\t" \
2977 "stw 3,60(1)\n\t" \
2978 /* arg9 */ \
2979 "lwz 3,36(11)\n\t" \
2980 "stw 3,56(1)\n\t" \
2981 /* args1-8 */ \
2982 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
2983 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
2984 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
2985 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
2986 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
2987 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
2988 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
2989 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
2990 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2991 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2992 "mr 11,%1\n\t" \
2993 "mr %0,3\n\t" \
2994 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
2995 VG_CONTRACT_FRAME_BY(72) \
2996 VG_CONTRACT_FRAME_BY(512) \
2997 : /*out*/ "=r" (_res) \
2998 : /*in*/ "r" (&_argvec[2]) \
2999 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3000 ); \
3001 lval = (__typeof__(lval)) _res; \
3002 } while (0)
3003
3004#endif /* PLAT_ppc32_aix5 */
3005
3006/* ------------------------ ppc64-aix5 ------------------------- */
3007
3008#if defined(PLAT_ppc64_aix5)
3009
3010/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3011
3012/* These regs are trashed by the hidden call. */
3013#define __CALLER_SAVED_REGS \
3014 "lr", "ctr", "xer", \
3015 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3016 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3017 "r11", "r12", "r13"
3018
3019/* Expand the stack frame, copying enough info that unwinding
3020 still works. Trashes r3. */
3021
3022#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3023 "addi 1,1,-" #_n_fr "\n\t" \
3024 "ld 3," #_n_fr "(1)\n\t" \
3025 "std 3,0(1)\n\t"
3026
3027#define VG_CONTRACT_FRAME_BY(_n_fr) \
3028 "addi 1,1," #_n_fr "\n\t"
3029
3030/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
3031 long) == 8. */
3032
3033#define CALL_FN_W_v(lval, orig) \
3034 do { \
3035 volatile OrigFn _orig = (orig); \
3036 volatile unsigned long _argvec[3+0]; \
3037 volatile unsigned long _res; \
3038 /* _argvec[0] holds current r2 across the call */ \
3039 _argvec[1] = (unsigned long)_orig.r2; \
3040 _argvec[2] = (unsigned long)_orig.nraddr; \
3041 __asm__ volatile( \
3042 "mr 11,%1\n\t" \
3043 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3044 "std 2,-16(11)\n\t" /* save tocptr */ \
3045 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3046 "ld 11, 0(11)\n\t" /* target->r11 */ \
3047 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3048 "mr 11,%1\n\t" \
3049 "mr %0,3\n\t" \
3050 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3051 VG_CONTRACT_FRAME_BY(512) \
3052 : /*out*/ "=r" (_res) \
3053 : /*in*/ "r" (&_argvec[2]) \
3054 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3055 ); \
3056 lval = (__typeof__(lval)) _res; \
3057 } while (0)
3058
3059#define CALL_FN_W_W(lval, orig, arg1) \
3060 do { \
3061 volatile OrigFn _orig = (orig); \
3062 volatile unsigned long _argvec[3+1]; \
3063 volatile unsigned long _res; \
3064 /* _argvec[0] holds current r2 across the call */ \
3065 _argvec[1] = (unsigned long)_orig.r2; \
3066 _argvec[2] = (unsigned long)_orig.nraddr; \
3067 _argvec[2+1] = (unsigned long)arg1; \
3068 __asm__ volatile( \
3069 "mr 11,%1\n\t" \
3070 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3071 "std 2,-16(11)\n\t" /* save tocptr */ \
3072 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3073 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3074 "ld 11, 0(11)\n\t" /* target->r11 */ \
3075 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3076 "mr 11,%1\n\t" \
3077 "mr %0,3\n\t" \
3078 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3079 VG_CONTRACT_FRAME_BY(512) \
3080 : /*out*/ "=r" (_res) \
3081 : /*in*/ "r" (&_argvec[2]) \
3082 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3083 ); \
3084 lval = (__typeof__(lval)) _res; \
3085 } while (0)
3086
3087#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3088 do { \
3089 volatile OrigFn _orig = (orig); \
3090 volatile unsigned long _argvec[3+2]; \
3091 volatile unsigned long _res; \
3092 /* _argvec[0] holds current r2 across the call */ \
3093 _argvec[1] = (unsigned long)_orig.r2; \
3094 _argvec[2] = (unsigned long)_orig.nraddr; \
3095 _argvec[2+1] = (unsigned long)arg1; \
3096 _argvec[2+2] = (unsigned long)arg2; \
3097 __asm__ volatile( \
3098 "mr 11,%1\n\t" \
3099 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3100 "std 2,-16(11)\n\t" /* save tocptr */ \
3101 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3102 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3103 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3104 "ld 11, 0(11)\n\t" /* target->r11 */ \
3105 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3106 "mr 11,%1\n\t" \
3107 "mr %0,3\n\t" \
3108 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3109 VG_CONTRACT_FRAME_BY(512) \
3110 : /*out*/ "=r" (_res) \
3111 : /*in*/ "r" (&_argvec[2]) \
3112 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3113 ); \
3114 lval = (__typeof__(lval)) _res; \
3115 } while (0)
3116
3117#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3118 do { \
3119 volatile OrigFn _orig = (orig); \
3120 volatile unsigned long _argvec[3+3]; \
3121 volatile unsigned long _res; \
3122 /* _argvec[0] holds current r2 across the call */ \
3123 _argvec[1] = (unsigned long)_orig.r2; \
3124 _argvec[2] = (unsigned long)_orig.nraddr; \
3125 _argvec[2+1] = (unsigned long)arg1; \
3126 _argvec[2+2] = (unsigned long)arg2; \
3127 _argvec[2+3] = (unsigned long)arg3; \
3128 __asm__ volatile( \
3129 "mr 11,%1\n\t" \
3130 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3131 "std 2,-16(11)\n\t" /* save tocptr */ \
3132 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3133 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3134 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3135 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3136 "ld 11, 0(11)\n\t" /* target->r11 */ \
3137 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3138 "mr 11,%1\n\t" \
3139 "mr %0,3\n\t" \
3140 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3141 VG_CONTRACT_FRAME_BY(512) \
3142 : /*out*/ "=r" (_res) \
3143 : /*in*/ "r" (&_argvec[2]) \
3144 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3145 ); \
3146 lval = (__typeof__(lval)) _res; \
3147 } while (0)
3148
3149#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3150 do { \
3151 volatile OrigFn _orig = (orig); \
3152 volatile unsigned long _argvec[3+4]; \
3153 volatile unsigned long _res; \
3154 /* _argvec[0] holds current r2 across the call */ \
3155 _argvec[1] = (unsigned long)_orig.r2; \
3156 _argvec[2] = (unsigned long)_orig.nraddr; \
3157 _argvec[2+1] = (unsigned long)arg1; \
3158 _argvec[2+2] = (unsigned long)arg2; \
3159 _argvec[2+3] = (unsigned long)arg3; \
3160 _argvec[2+4] = (unsigned long)arg4; \
3161 __asm__ volatile( \
3162 "mr 11,%1\n\t" \
3163 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3164 "std 2,-16(11)\n\t" /* save tocptr */ \
3165 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3166 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3167 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3168 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3169 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3170 "ld 11, 0(11)\n\t" /* target->r11 */ \
3171 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3172 "mr 11,%1\n\t" \
3173 "mr %0,3\n\t" \
3174 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3175 VG_CONTRACT_FRAME_BY(512) \
3176 : /*out*/ "=r" (_res) \
3177 : /*in*/ "r" (&_argvec[2]) \
3178 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3179 ); \
3180 lval = (__typeof__(lval)) _res; \
3181 } while (0)
3182
3183#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3184 do { \
3185 volatile OrigFn _orig = (orig); \
3186 volatile unsigned long _argvec[3+5]; \
3187 volatile unsigned long _res; \
3188 /* _argvec[0] holds current r2 across the call */ \
3189 _argvec[1] = (unsigned long)_orig.r2; \
3190 _argvec[2] = (unsigned long)_orig.nraddr; \
3191 _argvec[2+1] = (unsigned long)arg1; \
3192 _argvec[2+2] = (unsigned long)arg2; \
3193 _argvec[2+3] = (unsigned long)arg3; \
3194 _argvec[2+4] = (unsigned long)arg4; \
3195 _argvec[2+5] = (unsigned long)arg5; \
3196 __asm__ volatile( \
3197 "mr 11,%1\n\t" \
3198 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3199 "std 2,-16(11)\n\t" /* save tocptr */ \
3200 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3201 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3202 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3203 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3204 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3205 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3206 "ld 11, 0(11)\n\t" /* target->r11 */ \
3207 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3208 "mr 11,%1\n\t" \
3209 "mr %0,3\n\t" \
3210 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3211 VG_CONTRACT_FRAME_BY(512) \
3212 : /*out*/ "=r" (_res) \
3213 : /*in*/ "r" (&_argvec[2]) \
3214 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3215 ); \
3216 lval = (__typeof__(lval)) _res; \
3217 } while (0)
3218
3219#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3220 do { \
3221 volatile OrigFn _orig = (orig); \
3222 volatile unsigned long _argvec[3+6]; \
3223 volatile unsigned long _res; \
3224 /* _argvec[0] holds current r2 across the call */ \
3225 _argvec[1] = (unsigned long)_orig.r2; \
3226 _argvec[2] = (unsigned long)_orig.nraddr; \
3227 _argvec[2+1] = (unsigned long)arg1; \
3228 _argvec[2+2] = (unsigned long)arg2; \
3229 _argvec[2+3] = (unsigned long)arg3; \
3230 _argvec[2+4] = (unsigned long)arg4; \
3231 _argvec[2+5] = (unsigned long)arg5; \
3232 _argvec[2+6] = (unsigned long)arg6; \
3233 __asm__ volatile( \
3234 "mr 11,%1\n\t" \
3235 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3236 "std 2,-16(11)\n\t" /* save tocptr */ \
3237 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3238 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3239 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3240 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3241 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3242 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3243 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3244 "ld 11, 0(11)\n\t" /* target->r11 */ \
3245 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3246 "mr 11,%1\n\t" \
3247 "mr %0,3\n\t" \
3248 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3249 VG_CONTRACT_FRAME_BY(512) \
3250 : /*out*/ "=r" (_res) \
3251 : /*in*/ "r" (&_argvec[2]) \
3252 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3253 ); \
3254 lval = (__typeof__(lval)) _res; \
3255 } while (0)
3256
3257#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3258 arg7) \
3259 do { \
3260 volatile OrigFn _orig = (orig); \
3261 volatile unsigned long _argvec[3+7]; \
3262 volatile unsigned long _res; \
3263 /* _argvec[0] holds current r2 across the call */ \
3264 _argvec[1] = (unsigned long)_orig.r2; \
3265 _argvec[2] = (unsigned long)_orig.nraddr; \
3266 _argvec[2+1] = (unsigned long)arg1; \
3267 _argvec[2+2] = (unsigned long)arg2; \
3268 _argvec[2+3] = (unsigned long)arg3; \
3269 _argvec[2+4] = (unsigned long)arg4; \
3270 _argvec[2+5] = (unsigned long)arg5; \
3271 _argvec[2+6] = (unsigned long)arg6; \
3272 _argvec[2+7] = (unsigned long)arg7; \
3273 __asm__ volatile( \
3274 "mr 11,%1\n\t" \
3275 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3276 "std 2,-16(11)\n\t" /* save tocptr */ \
3277 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3278 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3279 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3280 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3281 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3282 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3283 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3284 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3285 "ld 11, 0(11)\n\t" /* target->r11 */ \
3286 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3287 "mr 11,%1\n\t" \
3288 "mr %0,3\n\t" \
3289 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3290 VG_CONTRACT_FRAME_BY(512) \
3291 : /*out*/ "=r" (_res) \
3292 : /*in*/ "r" (&_argvec[2]) \
3293 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3294 ); \
3295 lval = (__typeof__(lval)) _res; \
3296 } while (0)
3297
3298#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3299 arg7,arg8) \
3300 do { \
3301 volatile OrigFn _orig = (orig); \
3302 volatile unsigned long _argvec[3+8]; \
3303 volatile unsigned long _res; \
3304 /* _argvec[0] holds current r2 across the call */ \
3305 _argvec[1] = (unsigned long)_orig.r2; \
3306 _argvec[2] = (unsigned long)_orig.nraddr; \
3307 _argvec[2+1] = (unsigned long)arg1; \
3308 _argvec[2+2] = (unsigned long)arg2; \
3309 _argvec[2+3] = (unsigned long)arg3; \
3310 _argvec[2+4] = (unsigned long)arg4; \
3311 _argvec[2+5] = (unsigned long)arg5; \
3312 _argvec[2+6] = (unsigned long)arg6; \
3313 _argvec[2+7] = (unsigned long)arg7; \
3314 _argvec[2+8] = (unsigned long)arg8; \
3315 __asm__ volatile( \
3316 "mr 11,%1\n\t" \
3317 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3318 "std 2,-16(11)\n\t" /* save tocptr */ \
3319 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3320 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3321 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3322 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3323 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3324 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3325 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3326 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3327 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3328 "ld 11, 0(11)\n\t" /* target->r11 */ \
3329 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3330 "mr 11,%1\n\t" \
3331 "mr %0,3\n\t" \
3332 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3333 VG_CONTRACT_FRAME_BY(512) \
3334 : /*out*/ "=r" (_res) \
3335 : /*in*/ "r" (&_argvec[2]) \
3336 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3337 ); \
3338 lval = (__typeof__(lval)) _res; \
3339 } while (0)
3340
3341#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3342 arg7,arg8,arg9) \
3343 do { \
3344 volatile OrigFn _orig = (orig); \
3345 volatile unsigned long _argvec[3+9]; \
3346 volatile unsigned long _res; \
3347 /* _argvec[0] holds current r2 across the call */ \
3348 _argvec[1] = (unsigned long)_orig.r2; \
3349 _argvec[2] = (unsigned long)_orig.nraddr; \
3350 _argvec[2+1] = (unsigned long)arg1; \
3351 _argvec[2+2] = (unsigned long)arg2; \
3352 _argvec[2+3] = (unsigned long)arg3; \
3353 _argvec[2+4] = (unsigned long)arg4; \
3354 _argvec[2+5] = (unsigned long)arg5; \
3355 _argvec[2+6] = (unsigned long)arg6; \
3356 _argvec[2+7] = (unsigned long)arg7; \
3357 _argvec[2+8] = (unsigned long)arg8; \
3358 _argvec[2+9] = (unsigned long)arg9; \
3359 __asm__ volatile( \
3360 "mr 11,%1\n\t" \
3361 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3362 "std 2,-16(11)\n\t" /* save tocptr */ \
3363 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3364 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3365 /* arg9 */ \
3366 "ld 3,72(11)\n\t" \
3367 "std 3,112(1)\n\t" \
3368 /* args1-8 */ \
3369 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3370 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3371 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3372 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3373 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3374 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3375 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3376 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3377 "ld 11, 0(11)\n\t" /* target->r11 */ \
3378 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3379 "mr 11,%1\n\t" \
3380 "mr %0,3\n\t" \
3381 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3382 VG_CONTRACT_FRAME_BY(128) \
3383 VG_CONTRACT_FRAME_BY(512) \
3384 : /*out*/ "=r" (_res) \
3385 : /*in*/ "r" (&_argvec[2]) \
3386 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3387 ); \
3388 lval = (__typeof__(lval)) _res; \
3389 } while (0)
3390
3391#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3392 arg7,arg8,arg9,arg10) \
3393 do { \
3394 volatile OrigFn _orig = (orig); \
3395 volatile unsigned long _argvec[3+10]; \
3396 volatile unsigned long _res; \
3397 /* _argvec[0] holds current r2 across the call */ \
3398 _argvec[1] = (unsigned long)_orig.r2; \
3399 _argvec[2] = (unsigned long)_orig.nraddr; \
3400 _argvec[2+1] = (unsigned long)arg1; \
3401 _argvec[2+2] = (unsigned long)arg2; \
3402 _argvec[2+3] = (unsigned long)arg3; \
3403 _argvec[2+4] = (unsigned long)arg4; \
3404 _argvec[2+5] = (unsigned long)arg5; \
3405 _argvec[2+6] = (unsigned long)arg6; \
3406 _argvec[2+7] = (unsigned long)arg7; \
3407 _argvec[2+8] = (unsigned long)arg8; \
3408 _argvec[2+9] = (unsigned long)arg9; \
3409 _argvec[2+10] = (unsigned long)arg10; \
3410 __asm__ volatile( \
3411 "mr 11,%1\n\t" \
3412 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3413 "std 2,-16(11)\n\t" /* save tocptr */ \
3414 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3415 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3416 /* arg10 */ \
3417 "ld 3,80(11)\n\t" \
3418 "std 3,120(1)\n\t" \
3419 /* arg9 */ \
3420 "ld 3,72(11)\n\t" \
3421 "std 3,112(1)\n\t" \
3422 /* args1-8 */ \
3423 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3424 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3425 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3426 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3427 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3428 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3429 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3430 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3431 "ld 11, 0(11)\n\t" /* target->r11 */ \
3432 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3433 "mr 11,%1\n\t" \
3434 "mr %0,3\n\t" \
3435 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3436 VG_CONTRACT_FRAME_BY(128) \
3437 VG_CONTRACT_FRAME_BY(512) \
3438 : /*out*/ "=r" (_res) \
3439 : /*in*/ "r" (&_argvec[2]) \
3440 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3441 ); \
3442 lval = (__typeof__(lval)) _res; \
3443 } while (0)
3444
3445#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3446 arg7,arg8,arg9,arg10,arg11) \
3447 do { \
3448 volatile OrigFn _orig = (orig); \
3449 volatile unsigned long _argvec[3+11]; \
3450 volatile unsigned long _res; \
3451 /* _argvec[0] holds current r2 across the call */ \
3452 _argvec[1] = (unsigned long)_orig.r2; \
3453 _argvec[2] = (unsigned long)_orig.nraddr; \
3454 _argvec[2+1] = (unsigned long)arg1; \
3455 _argvec[2+2] = (unsigned long)arg2; \
3456 _argvec[2+3] = (unsigned long)arg3; \
3457 _argvec[2+4] = (unsigned long)arg4; \
3458 _argvec[2+5] = (unsigned long)arg5; \
3459 _argvec[2+6] = (unsigned long)arg6; \
3460 _argvec[2+7] = (unsigned long)arg7; \
3461 _argvec[2+8] = (unsigned long)arg8; \
3462 _argvec[2+9] = (unsigned long)arg9; \
3463 _argvec[2+10] = (unsigned long)arg10; \
3464 _argvec[2+11] = (unsigned long)arg11; \
3465 __asm__ volatile( \
3466 "mr 11,%1\n\t" \
3467 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3468 "std 2,-16(11)\n\t" /* save tocptr */ \
3469 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3470 VG_EXPAND_FRAME_BY_trashes_r3(144) \
3471 /* arg11 */ \
3472 "ld 3,88(11)\n\t" \
3473 "std 3,128(1)\n\t" \
3474 /* arg10 */ \
3475 "ld 3,80(11)\n\t" \
3476 "std 3,120(1)\n\t" \
3477 /* arg9 */ \
3478 "ld 3,72(11)\n\t" \
3479 "std 3,112(1)\n\t" \
3480 /* args1-8 */ \
3481 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3482 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3483 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3484 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3485 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3486 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3487 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3488 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3489 "ld 11, 0(11)\n\t" /* target->r11 */ \
3490 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3491 "mr 11,%1\n\t" \
3492 "mr %0,3\n\t" \
3493 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3494 VG_CONTRACT_FRAME_BY(144) \
3495 VG_CONTRACT_FRAME_BY(512) \
3496 : /*out*/ "=r" (_res) \
3497 : /*in*/ "r" (&_argvec[2]) \
3498 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3499 ); \
3500 lval = (__typeof__(lval)) _res; \
3501 } while (0)
3502
3503#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3504 arg7,arg8,arg9,arg10,arg11,arg12) \
3505 do { \
3506 volatile OrigFn _orig = (orig); \
3507 volatile unsigned long _argvec[3+12]; \
3508 volatile unsigned long _res; \
3509 /* _argvec[0] holds current r2 across the call */ \
3510 _argvec[1] = (unsigned long)_orig.r2; \
3511 _argvec[2] = (unsigned long)_orig.nraddr; \
3512 _argvec[2+1] = (unsigned long)arg1; \
3513 _argvec[2+2] = (unsigned long)arg2; \
3514 _argvec[2+3] = (unsigned long)arg3; \
3515 _argvec[2+4] = (unsigned long)arg4; \
3516 _argvec[2+5] = (unsigned long)arg5; \
3517 _argvec[2+6] = (unsigned long)arg6; \
3518 _argvec[2+7] = (unsigned long)arg7; \
3519 _argvec[2+8] = (unsigned long)arg8; \
3520 _argvec[2+9] = (unsigned long)arg9; \
3521 _argvec[2+10] = (unsigned long)arg10; \
3522 _argvec[2+11] = (unsigned long)arg11; \
3523 _argvec[2+12] = (unsigned long)arg12; \
3524 __asm__ volatile( \
3525 "mr 11,%1\n\t" \
3526 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3527 "std 2,-16(11)\n\t" /* save tocptr */ \
3528 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3529 VG_EXPAND_FRAME_BY_trashes_r3(144) \
3530 /* arg12 */ \
3531 "ld 3,96(11)\n\t" \
3532 "std 3,136(1)\n\t" \
3533 /* arg11 */ \
3534 "ld 3,88(11)\n\t" \
3535 "std 3,128(1)\n\t" \
3536 /* arg10 */ \
3537 "ld 3,80(11)\n\t" \
3538 "std 3,120(1)\n\t" \
3539 /* arg9 */ \
3540 "ld 3,72(11)\n\t" \
3541 "std 3,112(1)\n\t" \
3542 /* args1-8 */ \
3543 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3544 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3545 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3546 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3547 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3548 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3549 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3550 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3551 "ld 11, 0(11)\n\t" /* target->r11 */ \
3552 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3553 "mr 11,%1\n\t" \
3554 "mr %0,3\n\t" \
3555 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3556 VG_CONTRACT_FRAME_BY(144) \
3557 VG_CONTRACT_FRAME_BY(512) \
3558 : /*out*/ "=r" (_res) \
3559 : /*in*/ "r" (&_argvec[2]) \
3560 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3561 ); \
3562 lval = (__typeof__(lval)) _res; \
3563 } while (0)
3564
3565#endif /* PLAT_ppc64_aix5 */
sewardj9734b202006-01-17 01:49:37 +00003566
sewardj0ec07f32006-01-12 12:32:32 +00003567
3568/* ------------------------------------------------------------------ */
3569/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
3570/* */
njn30d76c62005-06-18 15:07:39 +00003571/* ------------------------------------------------------------------ */
3572
sewardj2e93c502002-04-12 11:12:52 +00003573/* Some request codes. There are many more of these, but most are not
3574 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00003575 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00003576
sewardj0ec07f32006-01-12 12:32:32 +00003577 Core ones are in the range 0x00000000--0x0000ffff. The non-public
3578 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00003579*/
3580
sewardj0ec07f32006-01-12 12:32:32 +00003581/* These macros are used by tools -- they must be public, but don't
3582 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00003583#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00003584 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00003585#define VG_IS_TOOL_USERREQ(a, b, v) \
3586 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00003587
sewardj5ce4b152006-03-11 12:57:41 +00003588/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
3589 This enum comprises an ABI exported by Valgrind to programs
3590 which use client requests. DO NOT CHANGE THE ORDER OF THESE
3591 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00003592typedef
njn4c791212003-05-02 17:53:54 +00003593 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
3594 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00003595
sewardj0ec07f32006-01-12 12:32:32 +00003596 /* These allow any function to be called from the simulated
3597 CPU but run on the real CPU. Nb: the first arg passed to
3598 the function is always the ThreadId of the running
3599 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00003600 function, etc. */
njn4c791212003-05-02 17:53:54 +00003601 VG_USERREQ__CLIENT_CALL0 = 0x1101,
3602 VG_USERREQ__CLIENT_CALL1 = 0x1102,
3603 VG_USERREQ__CLIENT_CALL2 = 0x1103,
3604 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00003605
sewardj0ec07f32006-01-12 12:32:32 +00003606 /* Can be useful in regression testing suites -- eg. can
3607 send Valgrind's output to /dev/null and still count
3608 errors. */
njn4c791212003-05-02 17:53:54 +00003609 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00003610
sewardj0ec07f32006-01-12 12:32:32 +00003611 /* These are useful and can be interpreted by any tool that
3612 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00003613 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
3614 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00003615 /* Memory pool support. */
3616 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
3617 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
3618 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
3619 VG_USERREQ__MEMPOOL_FREE = 0x1306,
sewardj2c1c9df2006-07-28 00:06:37 +00003620 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
sewardjc740d762006-10-05 17:59:23 +00003621 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
3622 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
3623 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
njnd7994182003-10-02 13:44:04 +00003624
fitzhardinge39de4b42003-10-31 07:12:21 +00003625 /* Allow printfs to valgrind log. */
njn30d76c62005-06-18 15:07:39 +00003626 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00003627 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
3628
3629 /* Stack support. */
3630 VG_USERREQ__STACK_REGISTER = 0x1501,
3631 VG_USERREQ__STACK_DEREGISTER = 0x1502,
sewardjc8259b82009-04-22 22:42:10 +00003632 VG_USERREQ__STACK_CHANGE = 0x1503,
3633
3634 /* Wine support */
3635 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601
njn25e49d8e72002-09-23 09:36:25 +00003636 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00003637
sewardj0ec07f32006-01-12 12:32:32 +00003638#if !defined(__GNUC__)
3639# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00003640#endif
sewardj2e93c502002-04-12 11:12:52 +00003641
sewardj0ec07f32006-01-12 12:32:32 +00003642/* Returns the number of Valgrinds this code is running under. That
3643 is, 0 if running natively, 1 if running under Valgrind, 2 if
3644 running under Valgrind which is running under another Valgrind,
3645 etc. */
3646#define RUNNING_ON_VALGRIND __extension__ \
3647 ({unsigned int _qzz_res; \
3648 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \
3649 VG_USERREQ__RUNNING_ON_VALGRIND, \
sewardj9af10a12006-02-01 14:59:42 +00003650 0, 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00003651 _qzz_res; \
sewardjde4a1d02002-03-22 01:27:54 +00003652 })
3653
3654
sewardj18d75132002-05-16 11:06:21 +00003655/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
3656 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
3657 since it provides a way to make sure valgrind will retranslate the
3658 invalidated area. Returns no value. */
sewardj0ec07f32006-01-12 12:32:32 +00003659#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
3660 {unsigned int _qzz_res; \
3661 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3662 VG_USERREQ__DISCARD_TRANSLATIONS, \
sewardj9af10a12006-02-01 14:59:42 +00003663 _qzz_addr, _qzz_len, 0, 0, 0); \
sewardj18d75132002-05-16 11:06:21 +00003664 }
3665
njn26aba4d2005-05-16 13:31:23 +00003666
sewardj0ec07f32006-01-12 12:32:32 +00003667/* These requests are for getting Valgrind itself to print something.
3668 Possibly with a backtrace. This is a really ugly hack. */
3669
3670#if defined(NVALGRIND)
3671
3672# define VALGRIND_PRINTF(...)
3673# define VALGRIND_PRINTF_BACKTRACE(...)
njn26aba4d2005-05-16 13:31:23 +00003674
3675#else /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00003676
sewardj7eca0cc2006-04-12 17:15:35 +00003677/* Modern GCC will optimize the static routine out if unused,
3678 and unused attribute will shut down warnings about it. */
3679static int VALGRIND_PRINTF(const char *format, ...)
3680 __attribute__((format(__printf__, 1, 2), __unused__));
3681static int
fitzhardingea09a1b52003-11-07 23:09:48 +00003682VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00003683{
njnc6168192004-11-29 13:54:10 +00003684 unsigned long _qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00003685 va_list vargs;
3686 va_start(vargs, format);
sewardj0ec07f32006-01-12 12:32:32 +00003687 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF,
sewardj9af10a12006-02-01 14:59:42 +00003688 (unsigned long)format, (unsigned long)vargs,
3689 0, 0, 0);
fitzhardinge39de4b42003-10-31 07:12:21 +00003690 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00003691 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00003692}
3693
sewardj7eca0cc2006-04-12 17:15:35 +00003694static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
3695 __attribute__((format(__printf__, 1, 2), __unused__));
3696static int
fitzhardingea09a1b52003-11-07 23:09:48 +00003697VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00003698{
njnc6168192004-11-29 13:54:10 +00003699 unsigned long _qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00003700 va_list vargs;
3701 va_start(vargs, format);
sewardj0ec07f32006-01-12 12:32:32 +00003702 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE,
sewardj9af10a12006-02-01 14:59:42 +00003703 (unsigned long)format, (unsigned long)vargs,
3704 0, 0, 0);
fitzhardinge39de4b42003-10-31 07:12:21 +00003705 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00003706 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00003707}
3708
fitzhardinge39de4b42003-10-31 07:12:21 +00003709#endif /* NVALGRIND */
sewardj18d75132002-05-16 11:06:21 +00003710
sewardj0ec07f32006-01-12 12:32:32 +00003711
njn3e884182003-04-15 13:03:23 +00003712/* These requests allow control to move from the simulated CPU to the
njn1319b492006-11-20 22:02:40 +00003713 real CPU, calling an arbitary function.
3714
3715 Note that the current ThreadId is inserted as the first argument.
3716 So this call:
3717
3718 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
3719
3720 requires f to have this signature:
3721
3722 Word f(Word tid, Word arg1, Word arg2)
3723
3724 where "Word" is a word-sized type.
njn45fb4d32007-12-05 21:51:50 +00003725
3726 Note that these client requests are not entirely reliable. For example,
3727 if you call a function with them that subsequently calls printf(),
3728 there's a high chance Valgrind will crash. Generally, your prospects of
3729 these working are made higher if the called function does not refer to
3730 any global variables, and does not refer to any libc or other functions
3731 (printf et al). Any kind of entanglement with libc or dynamic linking is
3732 likely to have a bad outcome, for tricky reasons which we've grappled
3733 with a lot in the past.
njn1319b492006-11-20 22:02:40 +00003734*/
sewardj0ec07f32006-01-12 12:32:32 +00003735#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
sewardj315dc8d2006-08-28 21:13:06 +00003736 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00003737 ({unsigned long _qyy_res; \
3738 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3739 VG_USERREQ__CLIENT_CALL0, \
3740 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00003741 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00003742 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00003743 })
3744
sewardj0ec07f32006-01-12 12:32:32 +00003745#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
sewardj315dc8d2006-08-28 21:13:06 +00003746 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00003747 ({unsigned long _qyy_res; \
3748 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3749 VG_USERREQ__CLIENT_CALL1, \
3750 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00003751 _qyy_arg1, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00003752 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00003753 })
3754
sewardj0ec07f32006-01-12 12:32:32 +00003755#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
sewardj315dc8d2006-08-28 21:13:06 +00003756 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00003757 ({unsigned long _qyy_res; \
3758 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3759 VG_USERREQ__CLIENT_CALL2, \
3760 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00003761 _qyy_arg1, _qyy_arg2, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00003762 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00003763 })
3764
sewardj0ec07f32006-01-12 12:32:32 +00003765#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
sewardj315dc8d2006-08-28 21:13:06 +00003766 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00003767 ({unsigned long _qyy_res; \
3768 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3769 VG_USERREQ__CLIENT_CALL3, \
3770 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00003771 _qyy_arg1, _qyy_arg2, \
3772 _qyy_arg3, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00003773 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00003774 })
3775
3776
nethercote7cc9c232004-01-21 15:08:04 +00003777/* Counts the number of errors that have been recorded by a tool. Nb:
3778 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00003779 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00003780#define VALGRIND_COUNT_ERRORS \
sewardj315dc8d2006-08-28 21:13:06 +00003781 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00003782 ({unsigned int _qyy_res; \
3783 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
3784 VG_USERREQ__COUNT_ERRORS, \
sewardj9af10a12006-02-01 14:59:42 +00003785 0, 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00003786 _qyy_res; \
njn47363ab2003-04-21 13:24:40 +00003787 })
3788
njnd7994182003-10-02 13:44:04 +00003789/* Mark a block of memory as having been allocated by a malloc()-like
3790 function. `addr' is the start of the usable block (ie. after any
3791 redzone) `rzB' is redzone size if the allocator can apply redzones;
3792 use '0' if not. Adding redzones makes it more likely Valgrind will spot
3793 block overruns. `is_zeroed' indicates if the memory is zeroed, as it is
3794 for calloc(). Put it immediately after the point where a block is
3795 allocated.
3796
njn0fc5cbd2006-10-18 21:50:26 +00003797 If you're using Memcheck: If you're allocating memory via superblocks,
3798 and then handing out small chunks of each superblock, if you don't have
3799 redzones on your small blocks, it's worth marking the superblock with
3800 VALGRIND_MAKE_MEM_NOACCESS when it's created, so that block overruns are
3801 detected. But if you can put redzones on, it's probably better to not do
3802 this, so that messages for small overruns are described in terms of the
3803 small block rather than the superblock (but if you have a big overrun
3804 that skips over a redzone, you could miss an error this way). See
3805 memcheck/tests/custom_alloc.c for an example.
njnd7994182003-10-02 13:44:04 +00003806
njn479db772006-06-02 22:32:02 +00003807 WARNING: if your allocator uses malloc() or 'new' to allocate
3808 superblocks, rather than mmap() or brk(), this will not work properly --
3809 you'll likely get assertion failures during leak detection. This is
3810 because Valgrind doesn't like seeing overlapping heap blocks. Sorry.
3811
njnd7994182003-10-02 13:44:04 +00003812 Nb: block must be freed via a free()-like function specified
3813 with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */
sewardj0ec07f32006-01-12 12:32:32 +00003814#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
3815 {unsigned int _qzz_res; \
3816 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3817 VG_USERREQ__MALLOCLIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00003818 addr, sizeB, rzB, is_zeroed, 0); \
njnd7994182003-10-02 13:44:04 +00003819 }
3820
3821/* Mark a block of memory as having been freed by a free()-like function.
3822 `rzB' is redzone size; it must match that given to
3823 VALGRIND_MALLOCLIKE_BLOCK. Memory not freed will be detected by the leak
3824 checker. Put it immediately after the point where the block is freed. */
sewardj0ec07f32006-01-12 12:32:32 +00003825#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
3826 {unsigned int _qzz_res; \
3827 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3828 VG_USERREQ__FREELIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00003829 addr, rzB, 0, 0, 0); \
njnd7994182003-10-02 13:44:04 +00003830 }
3831
rjwalshbc0bb832004-06-19 18:12:36 +00003832/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003833#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
3834 {unsigned int _qzz_res; \
3835 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3836 VG_USERREQ__CREATE_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00003837 pool, rzB, is_zeroed, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00003838 }
3839
3840/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003841#define VALGRIND_DESTROY_MEMPOOL(pool) \
3842 {unsigned int _qzz_res; \
3843 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3844 VG_USERREQ__DESTROY_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00003845 pool, 0, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00003846 }
3847
3848/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003849#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
3850 {unsigned int _qzz_res; \
3851 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3852 VG_USERREQ__MEMPOOL_ALLOC, \
sewardj9af10a12006-02-01 14:59:42 +00003853 pool, addr, size, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00003854 }
3855
3856/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00003857#define VALGRIND_MEMPOOL_FREE(pool, addr) \
3858 {unsigned int _qzz_res; \
3859 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3860 VG_USERREQ__MEMPOOL_FREE, \
sewardj9af10a12006-02-01 14:59:42 +00003861 pool, addr, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00003862 }
3863
sewardj2c1c9df2006-07-28 00:06:37 +00003864/* Disassociate any pieces outside a particular range. */
3865#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
3866 {unsigned int _qzz_res; \
3867 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3868 VG_USERREQ__MEMPOOL_TRIM, \
3869 pool, addr, size, 0, 0); \
3870 }
3871
sewardjc740d762006-10-05 17:59:23 +00003872/* Resize and/or move a piece associated with a memory pool. */
3873#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
3874 {unsigned int _qzz_res; \
3875 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3876 VG_USERREQ__MOVE_MEMPOOL, \
3877 poolA, poolB, 0, 0, 0); \
3878 }
3879
3880/* Resize and/or move a piece associated with a memory pool. */
3881#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
3882 {unsigned int _qzz_res; \
3883 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3884 VG_USERREQ__MEMPOOL_CHANGE, \
3885 pool, addrA, addrB, size, 0); \
3886 }
3887
3888/* Return 1 if a mempool exists, else 0. */
3889#define VALGRIND_MEMPOOL_EXISTS(pool) \
njn44862972009-02-23 02:08:24 +00003890 __extension__ \
sewardjc740d762006-10-05 17:59:23 +00003891 ({unsigned int _qzz_res; \
3892 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3893 VG_USERREQ__MEMPOOL_EXISTS, \
3894 pool, 0, 0, 0, 0); \
3895 _qzz_res; \
3896 })
3897
rjwalsh0140af52005-06-04 20:42:33 +00003898/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00003899#define VALGRIND_STACK_REGISTER(start, end) \
njn44862972009-02-23 02:08:24 +00003900 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00003901 ({unsigned int _qzz_res; \
3902 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3903 VG_USERREQ__STACK_REGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00003904 start, end, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00003905 _qzz_res; \
rjwalsh0140af52005-06-04 20:42:33 +00003906 })
3907
3908/* Unmark the piece of memory associated with a stack id as being a
3909 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00003910#define VALGRIND_STACK_DEREGISTER(id) \
3911 {unsigned int _qzz_res; \
3912 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3913 VG_USERREQ__STACK_DEREGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00003914 id, 0, 0, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00003915 }
3916
3917/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00003918#define VALGRIND_STACK_CHANGE(id, start, end) \
3919 {unsigned int _qzz_res; \
3920 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3921 VG_USERREQ__STACK_CHANGE, \
sewardj9af10a12006-02-01 14:59:42 +00003922 id, start, end, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00003923 }
3924
sewardjc8259b82009-04-22 22:42:10 +00003925/* Load PDB debug info for Wine PE image_map. */
3926#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
3927 {unsigned int _qzz_res; \
3928 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
3929 VG_USERREQ__LOAD_PDB_DEBUGINFO, \
3930 fd, ptr, total_size, delta, 0); \
3931 }
3932
sewardj0ec07f32006-01-12 12:32:32 +00003933
sewardjf5c1a7f2006-10-17 01:32:48 +00003934#undef PLAT_x86_linux
3935#undef PLAT_amd64_linux
3936#undef PLAT_ppc32_linux
3937#undef PLAT_ppc64_linux
3938#undef PLAT_ppc32_aix5
3939#undef PLAT_ppc64_aix5
sewardj0ec07f32006-01-12 12:32:32 +00003940
njn3e884182003-04-15 13:03:23 +00003941#endif /* __VALGRIND_H */