blob: 65993fbb32f004d566d915197c5b992bbbb8c140 [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
sewardj71044162010-03-03 22:57:47 +000076
77/* ------------------------------------------------------------------ */
78/* VERSION NUMBER OF VALGRIND */
79/* ------------------------------------------------------------------ */
80
81/* Specify Valgrind's version number, so that user code can
82 conditionally compile based on our version number. */
83#define __VALGRIND__ 3
84#define __VALGRIND_MINOR__ 6
85
86
fitzhardinge39de4b42003-10-31 07:12:21 +000087#include <stdarg.h>
88
njn3dd0a912005-06-28 19:44:10 +000089/* Nb: this file might be included in a file compiled with -ansi. So
90 we can't use C++ style "//" comments nor the "asm" keyword (instead
91 use "__asm__"). */
92
sewardjf5c1a7f2006-10-17 01:32:48 +000093/* Derive some tags indicating what the target platform is. Note
sewardj0ec07f32006-01-12 12:32:32 +000094 that in this file we're using the compiler's CPP symbols for
95 identifying architectures, which are different to the ones we use
96 within the rest of Valgrind. Note, __powerpc__ is active for both
97 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
sewardj59570ff2010-01-01 11:59:33 +000098 latter (on Linux, that is).
99
100 Misc note: how to find out what's predefined in gcc by default:
101 gcc -Wp,-dM somefile.c
102*/
sewardj7af32302010-01-02 10:37:58 +0000103#undef PLAT_ppc64_aix5
104#undef PLAT_ppc32_aix5
105#undef PLAT_x86_darwin
106#undef PLAT_amd64_darwin
sewardjf5c1a7f2006-10-17 01:32:48 +0000107#undef PLAT_x86_linux
108#undef PLAT_amd64_linux
109#undef PLAT_ppc32_linux
110#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +0000111#undef PLAT_arm_linux
sewardj0ec07f32006-01-12 12:32:32 +0000112
njnf76d27a2009-05-28 01:53:07 +0000113#if defined(_AIX) && defined(__64BIT__)
sewardjf5c1a7f2006-10-17 01:32:48 +0000114# define PLAT_ppc64_aix5 1
115#elif defined(_AIX) && !defined(__64BIT__)
116# define PLAT_ppc32_aix5 1
njnf76d27a2009-05-28 01:53:07 +0000117#elif defined(__APPLE__) && defined(__i386__)
118# define PLAT_x86_darwin 1
119#elif defined(__APPLE__) && defined(__x86_64__)
120# define PLAT_amd64_darwin 1
sewardj59570ff2010-01-01 11:59:33 +0000121#elif defined(__linux__) && defined(__i386__)
njnf76d27a2009-05-28 01:53:07 +0000122# define PLAT_x86_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000123#elif defined(__linux__) && defined(__x86_64__)
njnf76d27a2009-05-28 01:53:07 +0000124# define PLAT_amd64_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000125#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000126# define PLAT_ppc32_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000127#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
njnf76d27a2009-05-28 01:53:07 +0000128# define PLAT_ppc64_linux 1
sewardj59570ff2010-01-01 11:59:33 +0000129#elif defined(__linux__) && defined(__arm__)
130# define PLAT_arm_linux 1
njnf76d27a2009-05-28 01:53:07 +0000131#else
sewardjf5c1a7f2006-10-17 01:32:48 +0000132/* If we're not compiling for our target platform, don't generate
sewardj0ec07f32006-01-12 12:32:32 +0000133 any inline asms. */
sewardj0ec07f32006-01-12 12:32:32 +0000134# if !defined(NVALGRIND)
135# define NVALGRIND 1
136# endif
137#endif
138
139
njn30d76c62005-06-18 15:07:39 +0000140/* ------------------------------------------------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000141/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
142/* in here of use to end-users -- skip to the next section. */
njn30d76c62005-06-18 15:07:39 +0000143/* ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000144
sewardj0ec07f32006-01-12 12:32:32 +0000145#if defined(NVALGRIND)
njn26aba4d2005-05-16 13:31:23 +0000146
147/* Define NVALGRIND to completely remove the Valgrind magic sequence
sewardj0ec07f32006-01-12 12:32:32 +0000148 from the compiled code (analogous to NDEBUG's effects on
149 assert()) */
150#define VALGRIND_DO_CLIENT_REQUEST( \
151 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000152 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000153 { \
154 (_zzq_rlval) = (_zzq_default); \
njn26aba4d2005-05-16 13:31:23 +0000155 }
156
sewardj0ec07f32006-01-12 12:32:32 +0000157#else /* ! NVALGRIND */
nethercotee90c6832004-10-18 18:07:49 +0000158
sewardj0ec07f32006-01-12 12:32:32 +0000159/* The following defines the magic code sequences which the JITter
160 spots and handles magically. Don't look too closely at them as
161 they will rot your brain.
162
163 The assembly code sequences for all architectures is in this one
164 file. This is because this file must be stand-alone, and we don't
165 want to have multiple files.
166
167 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
168 value gets put in the return slot, so that everything works when
169 this is executed not under Valgrind. Args are passed in a memory
170 block, and so there's no intrinsic limit to the number that could
sewardj9af10a12006-02-01 14:59:42 +0000171 be passed, but it's currently five.
nethercotee90c6832004-10-18 18:07:49 +0000172
nethercote54265442004-10-26 12:56:58 +0000173 The macro args are:
174 _zzq_rlval result lvalue
175 _zzq_default default value (result returned when running on real CPU)
176 _zzq_request request code
sewardj9af10a12006-02-01 14:59:42 +0000177 _zzq_arg1..5 request params
nethercote54265442004-10-26 12:56:58 +0000178
sewardj0ec07f32006-01-12 12:32:32 +0000179 The other two macros are used to support function wrapping, and are
sewardjd68ac3e2006-01-20 14:31:57 +0000180 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
181 guest's NRADDR pseudo-register and whatever other information is
182 needed to safely run the call original from the wrapper: on
183 ppc64-linux, the R2 value at the divert point is also needed. This
184 information is abstracted into a user-visible type, OrigFn.
185
186 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
187 guest, but guarantees that the branch instruction will not be
188 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
189 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
190 complete inline asm, since it needs to be combined with more magic
191 inline asm stuff to be useful.
nethercotee90c6832004-10-18 18:07:49 +0000192*/
193
njnf76d27a2009-05-28 01:53:07 +0000194/* ------------------------- x86-{linux,darwin} ---------------- */
sewardjde4a4ab2005-03-23 13:10:32 +0000195
njnf76d27a2009-05-28 01:53:07 +0000196#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
sewardjc8858442006-01-20 15:17:20 +0000197
198typedef
199 struct {
200 unsigned int nraddr; /* where's the code? */
201 }
202 OrigFn;
203
sewardj0ec07f32006-01-12 12:32:32 +0000204#define __SPECIAL_INSTRUCTION_PREAMBLE \
205 "roll $3, %%edi ; roll $13, %%edi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000206 "roll $29, %%edi ; roll $19, %%edi\n\t"
sewardjde4a4ab2005-03-23 13:10:32 +0000207
sewardj0ec07f32006-01-12 12:32:32 +0000208#define VALGRIND_DO_CLIENT_REQUEST( \
209 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000210 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
211 { volatile unsigned int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000212 volatile unsigned int _zzq_result; \
213 _zzq_args[0] = (unsigned int)(_zzq_request); \
214 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
215 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
216 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
217 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000218 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000219 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
220 /* %EDX = client_request ( %EAX ) */ \
221 "xchgl %%ebx,%%ebx" \
222 : "=d" (_zzq_result) \
223 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
224 : "cc", "memory" \
225 ); \
226 _zzq_rlval = _zzq_result; \
cerion85665ca2005-06-20 15:51:07 +0000227 }
sewardj2c48c7b2005-11-29 13:05:56 +0000228
sewardjc8858442006-01-20 15:17:20 +0000229#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
230 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
231 volatile unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000232 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
233 /* %EAX = guest_NRADDR */ \
234 "xchgl %%ecx,%%ecx" \
235 : "=a" (__addr) \
236 : \
237 : "cc", "memory" \
238 ); \
sewardjc8858442006-01-20 15:17:20 +0000239 _zzq_orig->nraddr = __addr; \
sewardj2c48c7b2005-11-29 13:05:56 +0000240 }
sewardj0ec07f32006-01-12 12:32:32 +0000241
242#define VALGRIND_CALL_NOREDIR_EAX \
243 __SPECIAL_INSTRUCTION_PREAMBLE \
244 /* call-noredir *%EAX */ \
245 "xchgl %%edx,%%edx\n\t"
njnf76d27a2009-05-28 01:53:07 +0000246#endif /* PLAT_x86_linux || PLAT_x86_darwin */
sewardj0ec07f32006-01-12 12:32:32 +0000247
njnf76d27a2009-05-28 01:53:07 +0000248/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000249
njnf76d27a2009-05-28 01:53:07 +0000250#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardjc8858442006-01-20 15:17:20 +0000251
252typedef
253 struct {
254 unsigned long long int nraddr; /* where's the code? */
255 }
256 OrigFn;
257
sewardj0ec07f32006-01-12 12:32:32 +0000258#define __SPECIAL_INSTRUCTION_PREAMBLE \
259 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000260 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000261
262#define VALGRIND_DO_CLIENT_REQUEST( \
263 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000264 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
265 { volatile unsigned long long int _zzq_args[6]; \
sewardj0ec07f32006-01-12 12:32:32 +0000266 volatile unsigned long long int _zzq_result; \
267 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
268 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
269 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
270 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
271 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000272 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000273 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
274 /* %RDX = client_request ( %RAX ) */ \
275 "xchgq %%rbx,%%rbx" \
276 : "=d" (_zzq_result) \
277 : "a" (&_zzq_args[0]), "0" (_zzq_default) \
278 : "cc", "memory" \
279 ); \
280 _zzq_rlval = _zzq_result; \
281 }
282
sewardjc8858442006-01-20 15:17:20 +0000283#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
284 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
285 volatile unsigned long long int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000286 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
287 /* %RAX = guest_NRADDR */ \
288 "xchgq %%rcx,%%rcx" \
289 : "=a" (__addr) \
290 : \
291 : "cc", "memory" \
292 ); \
sewardjc8858442006-01-20 15:17:20 +0000293 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000294 }
295
296#define VALGRIND_CALL_NOREDIR_RAX \
297 __SPECIAL_INSTRUCTION_PREAMBLE \
298 /* call-noredir *%RAX */ \
299 "xchgq %%rdx,%%rdx\n\t"
njnf76d27a2009-05-28 01:53:07 +0000300#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +0000301
sewardjf5c1a7f2006-10-17 01:32:48 +0000302/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000303
sewardjf5c1a7f2006-10-17 01:32:48 +0000304#if defined(PLAT_ppc32_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000305
306typedef
307 struct {
sewardjc8858442006-01-20 15:17:20 +0000308 unsigned int nraddr; /* where's the code? */
sewardjd68ac3e2006-01-20 14:31:57 +0000309 }
310 OrigFn;
311
sewardj0ec07f32006-01-12 12:32:32 +0000312#define __SPECIAL_INSTRUCTION_PREAMBLE \
313 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
sewardj1a85f4f2006-01-12 21:15:35 +0000314 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
sewardj0ec07f32006-01-12 12:32:32 +0000315
316#define VALGRIND_DO_CLIENT_REQUEST( \
317 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000318 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000319 \
sewardj9af10a12006-02-01 14:59:42 +0000320 { unsigned int _zzq_args[6]; \
sewardj1c5bcb12006-12-08 21:29:46 +0000321 unsigned int _zzq_result; \
322 unsigned int* _zzq_ptr; \
sewardj0ec07f32006-01-12 12:32:32 +0000323 _zzq_args[0] = (unsigned int)(_zzq_request); \
324 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
325 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
326 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
327 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000328 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000329 _zzq_ptr = _zzq_args; \
sewardj1c5bcb12006-12-08 21:29:46 +0000330 __asm__ volatile("mr 3,%1\n\t" /*default*/ \
331 "mr 4,%2\n\t" /*ptr*/ \
332 __SPECIAL_INSTRUCTION_PREAMBLE \
sewardj0ec07f32006-01-12 12:32:32 +0000333 /* %R3 = client_request ( %R4 ) */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000334 "or 1,1,1\n\t" \
335 "mr %0,3" /*result*/ \
336 : "=b" (_zzq_result) \
337 : "b" (_zzq_default), "b" (_zzq_ptr) \
338 : "cc", "memory", "r3", "r4"); \
sewardj0ec07f32006-01-12 12:32:32 +0000339 _zzq_rlval = _zzq_result; \
340 }
341
sewardjd68ac3e2006-01-20 14:31:57 +0000342#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
343 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
sewardj1c5bcb12006-12-08 21:29:46 +0000344 unsigned int __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000345 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
346 /* %R3 = guest_NRADDR */ \
sewardj1c5bcb12006-12-08 21:29:46 +0000347 "or 2,2,2\n\t" \
348 "mr %0,3" \
349 : "=b" (__addr) \
sewardj0ec07f32006-01-12 12:32:32 +0000350 : \
sewardj1c5bcb12006-12-08 21:29:46 +0000351 : "cc", "memory", "r3" \
sewardj0ec07f32006-01-12 12:32:32 +0000352 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000353 _zzq_orig->nraddr = __addr; \
sewardj0ec07f32006-01-12 12:32:32 +0000354 }
355
356#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
357 __SPECIAL_INSTRUCTION_PREAMBLE \
358 /* branch-and-link-to-noredir *%R11 */ \
359 "or 3,3,3\n\t"
sewardjf5c1a7f2006-10-17 01:32:48 +0000360#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +0000361
sewardjf5c1a7f2006-10-17 01:32:48 +0000362/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +0000363
sewardjf5c1a7f2006-10-17 01:32:48 +0000364#if defined(PLAT_ppc64_linux)
sewardjd68ac3e2006-01-20 14:31:57 +0000365
366typedef
367 struct {
368 unsigned long long int nraddr; /* where's the code? */
369 unsigned long long int r2; /* what tocptr do we need? */
370 }
371 OrigFn;
372
sewardj1a85f4f2006-01-12 21:15:35 +0000373#define __SPECIAL_INSTRUCTION_PREAMBLE \
374 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
375 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
376
sewardj0ec07f32006-01-12 12:32:32 +0000377#define VALGRIND_DO_CLIENT_REQUEST( \
378 _zzq_rlval, _zzq_default, _zzq_request, \
sewardj9af10a12006-02-01 14:59:42 +0000379 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000380 \
sewardj9af10a12006-02-01 14:59:42 +0000381 { unsigned long long int _zzq_args[6]; \
sewardj1a85f4f2006-01-12 21:15:35 +0000382 register unsigned long long int _zzq_result __asm__("r3"); \
383 register unsigned long long int* _zzq_ptr __asm__("r4"); \
384 _zzq_args[0] = (unsigned long long int)(_zzq_request); \
385 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
386 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
387 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
388 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
sewardj9af10a12006-02-01 14:59:42 +0000389 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
sewardj0ec07f32006-01-12 12:32:32 +0000390 _zzq_ptr = _zzq_args; \
sewardj1a85f4f2006-01-12 21:15:35 +0000391 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
392 /* %R3 = client_request ( %R4 ) */ \
393 "or 1,1,1" \
394 : "=r" (_zzq_result) \
sewardj0ec07f32006-01-12 12:32:32 +0000395 : "0" (_zzq_default), "r" (_zzq_ptr) \
sewardj1a85f4f2006-01-12 21:15:35 +0000396 : "cc", "memory"); \
397 _zzq_rlval = _zzq_result; \
sewardj0ec07f32006-01-12 12:32:32 +0000398 }
sewardj1a85f4f2006-01-12 21:15:35 +0000399
sewardjd68ac3e2006-01-20 14:31:57 +0000400#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
401 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
402 register unsigned long long int __addr __asm__("r3"); \
sewardj1a85f4f2006-01-12 21:15:35 +0000403 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
404 /* %R3 = guest_NRADDR */ \
405 "or 2,2,2" \
406 : "=r" (__addr) \
407 : \
408 : "cc", "memory" \
409 ); \
sewardjd68ac3e2006-01-20 14:31:57 +0000410 _zzq_orig->nraddr = __addr; \
411 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
412 /* %R3 = guest_NRADDR_GPR2 */ \
413 "or 4,4,4" \
414 : "=r" (__addr) \
415 : \
416 : "cc", "memory" \
417 ); \
418 _zzq_orig->r2 = __addr; \
sewardj1a85f4f2006-01-12 21:15:35 +0000419 }
420
421#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
422 __SPECIAL_INSTRUCTION_PREAMBLE \
423 /* branch-and-link-to-noredir *%R11 */ \
424 "or 3,3,3\n\t"
425
sewardjf5c1a7f2006-10-17 01:32:48 +0000426#endif /* PLAT_ppc64_linux */
cerion85665ca2005-06-20 15:51:07 +0000427
sewardj59570ff2010-01-01 11:59:33 +0000428/* ------------------------- arm-linux ------------------------- */
429
430#if defined(PLAT_arm_linux)
431
432typedef
433 struct {
434 unsigned int nraddr; /* where's the code? */
435 }
436 OrigFn;
437
438#define __SPECIAL_INSTRUCTION_PREAMBLE \
439 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
440 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
441
442#define VALGRIND_DO_CLIENT_REQUEST( \
443 _zzq_rlval, _zzq_default, _zzq_request, \
444 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
445 \
446 { volatile unsigned int _zzq_args[6]; \
447 volatile unsigned int _zzq_result; \
448 _zzq_args[0] = (unsigned int)(_zzq_request); \
449 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
450 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
451 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
452 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
453 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
454 __asm__ volatile("mov r3, %1\n\t" /*default*/ \
455 "mov r4, %2\n\t" /*ptr*/ \
456 __SPECIAL_INSTRUCTION_PREAMBLE \
457 /* R3 = client_request ( R4 ) */ \
458 "orr r10, r10, r10\n\t" \
459 "mov %0, r3" /*result*/ \
460 : "=r" (_zzq_result) \
461 : "r" (_zzq_default), "r" (&_zzq_args[0]) \
462 : "cc","memory", "r3", "r4"); \
463 _zzq_rlval = _zzq_result; \
464 }
465
466#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
467 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
468 unsigned int __addr; \
469 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
470 /* R3 = guest_NRADDR */ \
471 "orr r11, r11, r11\n\t" \
472 "mov %0, r3" \
473 : "=r" (__addr) \
474 : \
475 : "cc", "memory", "r3" \
476 ); \
477 _zzq_orig->nraddr = __addr; \
478 }
479
480#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
481 __SPECIAL_INSTRUCTION_PREAMBLE \
482 /* branch-and-link-to-noredir *%R4 */ \
483 "orr r12, r12, r12\n\t"
484
485#endif /* PLAT_arm_linux */
486
sewardjf5c1a7f2006-10-17 01:32:48 +0000487/* ------------------------ ppc32-aix5 ------------------------- */
488
489#if defined(PLAT_ppc32_aix5)
490
491typedef
492 struct {
493 unsigned int nraddr; /* where's the code? */
494 unsigned int r2; /* what tocptr do we need? */
495 }
496 OrigFn;
497
498#define __SPECIAL_INSTRUCTION_PREAMBLE \
499 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
500 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
501
502#define VALGRIND_DO_CLIENT_REQUEST( \
503 _zzq_rlval, _zzq_default, _zzq_request, \
504 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
505 \
506 { unsigned int _zzq_args[7]; \
507 register unsigned int _zzq_result; \
508 register unsigned int* _zzq_ptr; \
509 _zzq_args[0] = (unsigned int)(_zzq_request); \
510 _zzq_args[1] = (unsigned int)(_zzq_arg1); \
511 _zzq_args[2] = (unsigned int)(_zzq_arg2); \
512 _zzq_args[3] = (unsigned int)(_zzq_arg3); \
513 _zzq_args[4] = (unsigned int)(_zzq_arg4); \
514 _zzq_args[5] = (unsigned int)(_zzq_arg5); \
515 _zzq_args[6] = (unsigned int)(_zzq_default); \
516 _zzq_ptr = _zzq_args; \
517 __asm__ volatile("mr 4,%1\n\t" \
518 "lwz 3, 24(4)\n\t" \
519 __SPECIAL_INSTRUCTION_PREAMBLE \
520 /* %R3 = client_request ( %R4 ) */ \
521 "or 1,1,1\n\t" \
522 "mr %0,3" \
523 : "=b" (_zzq_result) \
524 : "b" (_zzq_ptr) \
525 : "r3", "r4", "cc", "memory"); \
526 _zzq_rlval = _zzq_result; \
527 }
528
529#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
530 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
531 register unsigned int __addr; \
532 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
533 /* %R3 = guest_NRADDR */ \
534 "or 2,2,2\n\t" \
535 "mr %0,3" \
536 : "=b" (__addr) \
537 : \
538 : "r3", "cc", "memory" \
539 ); \
540 _zzq_orig->nraddr = __addr; \
541 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
542 /* %R3 = guest_NRADDR_GPR2 */ \
543 "or 4,4,4\n\t" \
544 "mr %0,3" \
545 : "=b" (__addr) \
546 : \
547 : "r3", "cc", "memory" \
548 ); \
549 _zzq_orig->r2 = __addr; \
550 }
551
552#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
553 __SPECIAL_INSTRUCTION_PREAMBLE \
554 /* branch-and-link-to-noredir *%R11 */ \
555 "or 3,3,3\n\t"
556
557#endif /* PLAT_ppc32_aix5 */
558
559/* ------------------------ ppc64-aix5 ------------------------- */
560
561#if defined(PLAT_ppc64_aix5)
562
563typedef
564 struct {
565 unsigned long long int nraddr; /* where's the code? */
566 unsigned long long int r2; /* what tocptr do we need? */
567 }
568 OrigFn;
569
570#define __SPECIAL_INSTRUCTION_PREAMBLE \
571 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
572 "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
573
574#define VALGRIND_DO_CLIENT_REQUEST( \
575 _zzq_rlval, _zzq_default, _zzq_request, \
576 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
577 \
578 { unsigned long long int _zzq_args[7]; \
579 register unsigned long long int _zzq_result; \
580 register unsigned long long int* _zzq_ptr; \
581 _zzq_args[0] = (unsigned int long long)(_zzq_request); \
582 _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
583 _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
584 _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
585 _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
586 _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
587 _zzq_args[6] = (unsigned int long long)(_zzq_default); \
588 _zzq_ptr = _zzq_args; \
589 __asm__ volatile("mr 4,%1\n\t" \
590 "ld 3, 48(4)\n\t" \
591 __SPECIAL_INSTRUCTION_PREAMBLE \
592 /* %R3 = client_request ( %R4 ) */ \
593 "or 1,1,1\n\t" \
594 "mr %0,3" \
595 : "=b" (_zzq_result) \
596 : "b" (_zzq_ptr) \
597 : "r3", "r4", "cc", "memory"); \
598 _zzq_rlval = _zzq_result; \
599 }
600
601#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
602 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
603 register unsigned long long int __addr; \
604 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
605 /* %R3 = guest_NRADDR */ \
606 "or 2,2,2\n\t" \
607 "mr %0,3" \
608 : "=b" (__addr) \
609 : \
610 : "r3", "cc", "memory" \
611 ); \
612 _zzq_orig->nraddr = __addr; \
613 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
614 /* %R3 = guest_NRADDR_GPR2 */ \
615 "or 4,4,4\n\t" \
616 "mr %0,3" \
617 : "=b" (__addr) \
618 : \
619 : "r3", "cc", "memory" \
620 ); \
621 _zzq_orig->r2 = __addr; \
622 }
623
624#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
625 __SPECIAL_INSTRUCTION_PREAMBLE \
626 /* branch-and-link-to-noredir *%R11 */ \
627 "or 3,3,3\n\t"
628
629#endif /* PLAT_ppc64_aix5 */
630
631/* Insert assembly code for other platforms here... */
njn26aba4d2005-05-16 13:31:23 +0000632
sewardj37091fb2002-11-16 11:06:50 +0000633#endif /* NVALGRIND */
sewardj2e93c502002-04-12 11:12:52 +0000634
nethercote69d9c462004-10-26 13:00:12 +0000635
njn30d76c62005-06-18 15:07:39 +0000636/* ------------------------------------------------------------------ */
sewardjf5c1a7f2006-10-17 01:32:48 +0000637/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
sewardj0ec07f32006-01-12 12:32:32 +0000638/* ugly. It's the least-worst tradeoff I can think of. */
639/* ------------------------------------------------------------------ */
640
641/* This section defines magic (a.k.a appalling-hack) macros for doing
642 guaranteed-no-redirection macros, so as to get from function
643 wrappers to the functions they are wrapping. The whole point is to
644 construct standard call sequences, but to do the call itself with a
645 special no-redirect call pseudo-instruction that the JIT
646 understands and handles specially. This section is long and
647 repetitious, and I can't see a way to make it shorter.
648
649 The naming scheme is as follows:
650
651 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
652
653 'W' stands for "word" and 'v' for "void". Hence there are
654 different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
655 and for each, the possibility of returning a word-typed result, or
656 no result.
657*/
658
659/* Use these to write the name of your wrapper. NOTE: duplicates
660 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
661
njn5f5ef2a2009-05-11 08:01:09 +0000662/* Use an extra level of macroisation so as to ensure the soname/fnname
663 args are fully macro-expanded before pasting them together. */
664#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
665
sewardj0ec07f32006-01-12 12:32:32 +0000666#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
njn5f5ef2a2009-05-11 08:01:09 +0000667 VG_CONCAT4(_vgwZU_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000668
669#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
njn5f5ef2a2009-05-11 08:01:09 +0000670 VG_CONCAT4(_vgwZZ_,soname,_,fnname)
sewardj0ec07f32006-01-12 12:32:32 +0000671
sewardjd68ac3e2006-01-20 14:31:57 +0000672/* Use this macro from within a wrapper function to collect the
673 context (address and possibly other info) of the original function.
674 Once you have that you can then use it in one of the CALL_FN_
675 macros. The type of the argument _lval is OrigFn. */
676#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
sewardj0ec07f32006-01-12 12:32:32 +0000677
678/* Derivatives of the main macros below, for calling functions
679 returning void. */
680
681#define CALL_FN_v_v(fnptr) \
682 do { volatile unsigned long _junk; \
683 CALL_FN_W_v(_junk,fnptr); } while (0)
684
685#define CALL_FN_v_W(fnptr, arg1) \
686 do { volatile unsigned long _junk; \
687 CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
688
689#define CALL_FN_v_WW(fnptr, arg1,arg2) \
690 do { volatile unsigned long _junk; \
691 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
692
sewardj5ce4b152006-03-11 12:57:41 +0000693#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
694 do { volatile unsigned long _junk; \
695 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
696
njn2b5f0a92009-05-19 01:24:50 +0000697#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
698 do { volatile unsigned long _junk; \
699 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
700
701#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
702 do { volatile unsigned long _junk; \
703 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
704
705#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
706 do { volatile unsigned long _junk; \
707 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
708
709#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
710 do { volatile unsigned long _junk; \
711 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
712
njnf76d27a2009-05-28 01:53:07 +0000713/* ------------------------- x86-{linux,darwin} ---------------- */
sewardj0ec07f32006-01-12 12:32:32 +0000714
njnf76d27a2009-05-28 01:53:07 +0000715#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
sewardj0ec07f32006-01-12 12:32:32 +0000716
717/* These regs are trashed by the hidden call. No need to mention eax
718 as gcc can already see that, plus causes gcc to bomb. */
719#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
720
721/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
722 long) == 4. */
723
sewardj66226cc2006-01-20 15:46:46 +0000724#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +0000725 do { \
sewardj66226cc2006-01-20 15:46:46 +0000726 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000727 volatile unsigned long _argvec[1]; \
728 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000729 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000730 __asm__ volatile( \
731 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
732 VALGRIND_CALL_NOREDIR_EAX \
733 : /*out*/ "=a" (_res) \
734 : /*in*/ "a" (&_argvec[0]) \
735 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
736 ); \
737 lval = (__typeof__(lval)) _res; \
738 } while (0)
739
sewardj66226cc2006-01-20 15:46:46 +0000740#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +0000741 do { \
sewardj66226cc2006-01-20 15:46:46 +0000742 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000743 volatile unsigned long _argvec[2]; \
744 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000745 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000746 _argvec[1] = (unsigned long)(arg1); \
747 __asm__ volatile( \
748 "pushl 4(%%eax)\n\t" \
749 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
750 VALGRIND_CALL_NOREDIR_EAX \
751 "addl $4, %%esp\n" \
752 : /*out*/ "=a" (_res) \
753 : /*in*/ "a" (&_argvec[0]) \
754 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
755 ); \
756 lval = (__typeof__(lval)) _res; \
757 } while (0)
758
sewardj66226cc2006-01-20 15:46:46 +0000759#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +0000760 do { \
sewardj66226cc2006-01-20 15:46:46 +0000761 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000762 volatile unsigned long _argvec[3]; \
763 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000764 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000765 _argvec[1] = (unsigned long)(arg1); \
766 _argvec[2] = (unsigned long)(arg2); \
767 __asm__ volatile( \
768 "pushl 8(%%eax)\n\t" \
769 "pushl 4(%%eax)\n\t" \
770 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
771 VALGRIND_CALL_NOREDIR_EAX \
772 "addl $8, %%esp\n" \
773 : /*out*/ "=a" (_res) \
774 : /*in*/ "a" (&_argvec[0]) \
775 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
776 ); \
777 lval = (__typeof__(lval)) _res; \
778 } while (0)
779
sewardj9e8b07a2006-02-18 21:13:29 +0000780#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
781 do { \
782 volatile OrigFn _orig = (orig); \
783 volatile unsigned long _argvec[4]; \
784 volatile unsigned long _res; \
785 _argvec[0] = (unsigned long)_orig.nraddr; \
786 _argvec[1] = (unsigned long)(arg1); \
787 _argvec[2] = (unsigned long)(arg2); \
788 _argvec[3] = (unsigned long)(arg3); \
789 __asm__ volatile( \
790 "pushl 12(%%eax)\n\t" \
791 "pushl 8(%%eax)\n\t" \
792 "pushl 4(%%eax)\n\t" \
793 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
794 VALGRIND_CALL_NOREDIR_EAX \
795 "addl $12, %%esp\n" \
796 : /*out*/ "=a" (_res) \
797 : /*in*/ "a" (&_argvec[0]) \
798 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
799 ); \
800 lval = (__typeof__(lval)) _res; \
801 } while (0)
802
sewardj66226cc2006-01-20 15:46:46 +0000803#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
sewardj0ec07f32006-01-12 12:32:32 +0000804 do { \
sewardj66226cc2006-01-20 15:46:46 +0000805 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000806 volatile unsigned long _argvec[5]; \
807 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000808 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000809 _argvec[1] = (unsigned long)(arg1); \
810 _argvec[2] = (unsigned long)(arg2); \
811 _argvec[3] = (unsigned long)(arg3); \
812 _argvec[4] = (unsigned long)(arg4); \
813 __asm__ volatile( \
814 "pushl 16(%%eax)\n\t" \
815 "pushl 12(%%eax)\n\t" \
816 "pushl 8(%%eax)\n\t" \
817 "pushl 4(%%eax)\n\t" \
818 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
819 VALGRIND_CALL_NOREDIR_EAX \
820 "addl $16, %%esp\n" \
821 : /*out*/ "=a" (_res) \
822 : /*in*/ "a" (&_argvec[0]) \
823 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
824 ); \
825 lval = (__typeof__(lval)) _res; \
826 } while (0)
827
sewardj66226cc2006-01-20 15:46:46 +0000828#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
sewardj0ec07f32006-01-12 12:32:32 +0000829 do { \
sewardj66226cc2006-01-20 15:46:46 +0000830 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000831 volatile unsigned long _argvec[6]; \
832 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000833 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000834 _argvec[1] = (unsigned long)(arg1); \
835 _argvec[2] = (unsigned long)(arg2); \
836 _argvec[3] = (unsigned long)(arg3); \
837 _argvec[4] = (unsigned long)(arg4); \
838 _argvec[5] = (unsigned long)(arg5); \
839 __asm__ volatile( \
840 "pushl 20(%%eax)\n\t" \
841 "pushl 16(%%eax)\n\t" \
842 "pushl 12(%%eax)\n\t" \
843 "pushl 8(%%eax)\n\t" \
844 "pushl 4(%%eax)\n\t" \
845 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
846 VALGRIND_CALL_NOREDIR_EAX \
847 "addl $20, %%esp\n" \
848 : /*out*/ "=a" (_res) \
849 : /*in*/ "a" (&_argvec[0]) \
850 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
851 ); \
852 lval = (__typeof__(lval)) _res; \
853 } while (0)
854
sewardj66226cc2006-01-20 15:46:46 +0000855#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
sewardj0ec07f32006-01-12 12:32:32 +0000856 do { \
sewardj66226cc2006-01-20 15:46:46 +0000857 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000858 volatile unsigned long _argvec[7]; \
859 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000860 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000861 _argvec[1] = (unsigned long)(arg1); \
862 _argvec[2] = (unsigned long)(arg2); \
863 _argvec[3] = (unsigned long)(arg3); \
864 _argvec[4] = (unsigned long)(arg4); \
865 _argvec[5] = (unsigned long)(arg5); \
866 _argvec[6] = (unsigned long)(arg6); \
867 __asm__ volatile( \
868 "pushl 24(%%eax)\n\t" \
869 "pushl 20(%%eax)\n\t" \
870 "pushl 16(%%eax)\n\t" \
871 "pushl 12(%%eax)\n\t" \
872 "pushl 8(%%eax)\n\t" \
873 "pushl 4(%%eax)\n\t" \
874 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
875 VALGRIND_CALL_NOREDIR_EAX \
876 "addl $24, %%esp\n" \
877 : /*out*/ "=a" (_res) \
878 : /*in*/ "a" (&_argvec[0]) \
879 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
880 ); \
881 lval = (__typeof__(lval)) _res; \
882 } while (0)
883
sewardj66226cc2006-01-20 15:46:46 +0000884#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
885 arg7) \
sewardj0ec07f32006-01-12 12:32:32 +0000886 do { \
sewardj66226cc2006-01-20 15:46:46 +0000887 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000888 volatile unsigned long _argvec[8]; \
889 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000890 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000891 _argvec[1] = (unsigned long)(arg1); \
892 _argvec[2] = (unsigned long)(arg2); \
893 _argvec[3] = (unsigned long)(arg3); \
894 _argvec[4] = (unsigned long)(arg4); \
895 _argvec[5] = (unsigned long)(arg5); \
896 _argvec[6] = (unsigned long)(arg6); \
897 _argvec[7] = (unsigned long)(arg7); \
898 __asm__ volatile( \
899 "pushl 28(%%eax)\n\t" \
900 "pushl 24(%%eax)\n\t" \
901 "pushl 20(%%eax)\n\t" \
902 "pushl 16(%%eax)\n\t" \
903 "pushl 12(%%eax)\n\t" \
904 "pushl 8(%%eax)\n\t" \
905 "pushl 4(%%eax)\n\t" \
906 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
907 VALGRIND_CALL_NOREDIR_EAX \
908 "addl $28, %%esp\n" \
909 : /*out*/ "=a" (_res) \
910 : /*in*/ "a" (&_argvec[0]) \
911 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
912 ); \
913 lval = (__typeof__(lval)) _res; \
914 } while (0)
915
sewardj66226cc2006-01-20 15:46:46 +0000916#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
917 arg7,arg8) \
sewardj0ec07f32006-01-12 12:32:32 +0000918 do { \
sewardj66226cc2006-01-20 15:46:46 +0000919 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +0000920 volatile unsigned long _argvec[9]; \
921 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +0000922 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +0000923 _argvec[1] = (unsigned long)(arg1); \
924 _argvec[2] = (unsigned long)(arg2); \
925 _argvec[3] = (unsigned long)(arg3); \
926 _argvec[4] = (unsigned long)(arg4); \
927 _argvec[5] = (unsigned long)(arg5); \
928 _argvec[6] = (unsigned long)(arg6); \
929 _argvec[7] = (unsigned long)(arg7); \
930 _argvec[8] = (unsigned long)(arg8); \
931 __asm__ volatile( \
932 "pushl 32(%%eax)\n\t" \
933 "pushl 28(%%eax)\n\t" \
934 "pushl 24(%%eax)\n\t" \
935 "pushl 20(%%eax)\n\t" \
936 "pushl 16(%%eax)\n\t" \
937 "pushl 12(%%eax)\n\t" \
938 "pushl 8(%%eax)\n\t" \
939 "pushl 4(%%eax)\n\t" \
940 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
941 VALGRIND_CALL_NOREDIR_EAX \
942 "addl $32, %%esp\n" \
943 : /*out*/ "=a" (_res) \
944 : /*in*/ "a" (&_argvec[0]) \
945 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
946 ); \
947 lval = (__typeof__(lval)) _res; \
948 } while (0)
949
sewardj45fa5b02006-03-09 19:06:23 +0000950#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
951 arg7,arg8,arg9) \
952 do { \
953 volatile OrigFn _orig = (orig); \
954 volatile unsigned long _argvec[10]; \
955 volatile unsigned long _res; \
956 _argvec[0] = (unsigned long)_orig.nraddr; \
957 _argvec[1] = (unsigned long)(arg1); \
958 _argvec[2] = (unsigned long)(arg2); \
959 _argvec[3] = (unsigned long)(arg3); \
960 _argvec[4] = (unsigned long)(arg4); \
961 _argvec[5] = (unsigned long)(arg5); \
962 _argvec[6] = (unsigned long)(arg6); \
963 _argvec[7] = (unsigned long)(arg7); \
964 _argvec[8] = (unsigned long)(arg8); \
965 _argvec[9] = (unsigned long)(arg9); \
966 __asm__ volatile( \
967 "pushl 36(%%eax)\n\t" \
968 "pushl 32(%%eax)\n\t" \
969 "pushl 28(%%eax)\n\t" \
970 "pushl 24(%%eax)\n\t" \
971 "pushl 20(%%eax)\n\t" \
972 "pushl 16(%%eax)\n\t" \
973 "pushl 12(%%eax)\n\t" \
974 "pushl 8(%%eax)\n\t" \
975 "pushl 4(%%eax)\n\t" \
976 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
977 VALGRIND_CALL_NOREDIR_EAX \
978 "addl $36, %%esp\n" \
979 : /*out*/ "=a" (_res) \
980 : /*in*/ "a" (&_argvec[0]) \
981 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
982 ); \
983 lval = (__typeof__(lval)) _res; \
984 } while (0)
985
986#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
987 arg7,arg8,arg9,arg10) \
988 do { \
989 volatile OrigFn _orig = (orig); \
990 volatile unsigned long _argvec[11]; \
991 volatile unsigned long _res; \
992 _argvec[0] = (unsigned long)_orig.nraddr; \
993 _argvec[1] = (unsigned long)(arg1); \
994 _argvec[2] = (unsigned long)(arg2); \
995 _argvec[3] = (unsigned long)(arg3); \
996 _argvec[4] = (unsigned long)(arg4); \
997 _argvec[5] = (unsigned long)(arg5); \
998 _argvec[6] = (unsigned long)(arg6); \
999 _argvec[7] = (unsigned long)(arg7); \
1000 _argvec[8] = (unsigned long)(arg8); \
1001 _argvec[9] = (unsigned long)(arg9); \
1002 _argvec[10] = (unsigned long)(arg10); \
1003 __asm__ volatile( \
1004 "pushl 40(%%eax)\n\t" \
1005 "pushl 36(%%eax)\n\t" \
1006 "pushl 32(%%eax)\n\t" \
1007 "pushl 28(%%eax)\n\t" \
1008 "pushl 24(%%eax)\n\t" \
1009 "pushl 20(%%eax)\n\t" \
1010 "pushl 16(%%eax)\n\t" \
1011 "pushl 12(%%eax)\n\t" \
1012 "pushl 8(%%eax)\n\t" \
1013 "pushl 4(%%eax)\n\t" \
1014 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1015 VALGRIND_CALL_NOREDIR_EAX \
1016 "addl $40, %%esp\n" \
1017 : /*out*/ "=a" (_res) \
1018 : /*in*/ "a" (&_argvec[0]) \
1019 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1020 ); \
1021 lval = (__typeof__(lval)) _res; \
1022 } while (0)
1023
sewardj5ce4b152006-03-11 12:57:41 +00001024#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1025 arg6,arg7,arg8,arg9,arg10, \
1026 arg11) \
1027 do { \
1028 volatile OrigFn _orig = (orig); \
1029 volatile unsigned long _argvec[12]; \
1030 volatile unsigned long _res; \
1031 _argvec[0] = (unsigned long)_orig.nraddr; \
1032 _argvec[1] = (unsigned long)(arg1); \
1033 _argvec[2] = (unsigned long)(arg2); \
1034 _argvec[3] = (unsigned long)(arg3); \
1035 _argvec[4] = (unsigned long)(arg4); \
1036 _argvec[5] = (unsigned long)(arg5); \
1037 _argvec[6] = (unsigned long)(arg6); \
1038 _argvec[7] = (unsigned long)(arg7); \
1039 _argvec[8] = (unsigned long)(arg8); \
1040 _argvec[9] = (unsigned long)(arg9); \
1041 _argvec[10] = (unsigned long)(arg10); \
1042 _argvec[11] = (unsigned long)(arg11); \
1043 __asm__ volatile( \
1044 "pushl 44(%%eax)\n\t" \
1045 "pushl 40(%%eax)\n\t" \
1046 "pushl 36(%%eax)\n\t" \
1047 "pushl 32(%%eax)\n\t" \
1048 "pushl 28(%%eax)\n\t" \
1049 "pushl 24(%%eax)\n\t" \
1050 "pushl 20(%%eax)\n\t" \
1051 "pushl 16(%%eax)\n\t" \
1052 "pushl 12(%%eax)\n\t" \
1053 "pushl 8(%%eax)\n\t" \
1054 "pushl 4(%%eax)\n\t" \
1055 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1056 VALGRIND_CALL_NOREDIR_EAX \
1057 "addl $44, %%esp\n" \
1058 : /*out*/ "=a" (_res) \
1059 : /*in*/ "a" (&_argvec[0]) \
1060 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1061 ); \
1062 lval = (__typeof__(lval)) _res; \
1063 } while (0)
1064
sewardj66226cc2006-01-20 15:46:46 +00001065#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1066 arg6,arg7,arg8,arg9,arg10, \
1067 arg11,arg12) \
sewardj0ec07f32006-01-12 12:32:32 +00001068 do { \
sewardj66226cc2006-01-20 15:46:46 +00001069 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001070 volatile unsigned long _argvec[13]; \
1071 volatile unsigned long _res; \
sewardj66226cc2006-01-20 15:46:46 +00001072 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001073 _argvec[1] = (unsigned long)(arg1); \
1074 _argvec[2] = (unsigned long)(arg2); \
1075 _argvec[3] = (unsigned long)(arg3); \
1076 _argvec[4] = (unsigned long)(arg4); \
1077 _argvec[5] = (unsigned long)(arg5); \
1078 _argvec[6] = (unsigned long)(arg6); \
1079 _argvec[7] = (unsigned long)(arg7); \
1080 _argvec[8] = (unsigned long)(arg8); \
1081 _argvec[9] = (unsigned long)(arg9); \
1082 _argvec[10] = (unsigned long)(arg10); \
1083 _argvec[11] = (unsigned long)(arg11); \
1084 _argvec[12] = (unsigned long)(arg12); \
1085 __asm__ volatile( \
1086 "pushl 48(%%eax)\n\t" \
1087 "pushl 44(%%eax)\n\t" \
1088 "pushl 40(%%eax)\n\t" \
1089 "pushl 36(%%eax)\n\t" \
1090 "pushl 32(%%eax)\n\t" \
1091 "pushl 28(%%eax)\n\t" \
1092 "pushl 24(%%eax)\n\t" \
1093 "pushl 20(%%eax)\n\t" \
1094 "pushl 16(%%eax)\n\t" \
1095 "pushl 12(%%eax)\n\t" \
1096 "pushl 8(%%eax)\n\t" \
1097 "pushl 4(%%eax)\n\t" \
1098 "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1099 VALGRIND_CALL_NOREDIR_EAX \
1100 "addl $48, %%esp\n" \
1101 : /*out*/ "=a" (_res) \
1102 : /*in*/ "a" (&_argvec[0]) \
1103 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1104 ); \
1105 lval = (__typeof__(lval)) _res; \
1106 } while (0)
1107
njnf76d27a2009-05-28 01:53:07 +00001108#endif /* PLAT_x86_linux || PLAT_x86_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001109
njnf76d27a2009-05-28 01:53:07 +00001110/* ------------------------ amd64-{linux,darwin} --------------- */
sewardj0ec07f32006-01-12 12:32:32 +00001111
njnf76d27a2009-05-28 01:53:07 +00001112#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
sewardj0ec07f32006-01-12 12:32:32 +00001113
1114/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1115
1116/* These regs are trashed by the hidden call. */
1117#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1118 "rdi", "r8", "r9", "r10", "r11"
1119
1120/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1121 long) == 8. */
1122
sewardja07c2e12007-11-09 23:09:50 +00001123/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1124 macros. In order not to trash the stack redzone, we need to drop
1125 %rsp by 128 before the hidden call, and restore afterwards. The
1126 nastyness is that it is only by luck that the stack still appears
1127 to be unwindable during the hidden call - since then the behaviour
1128 of any routine using this macro does not match what the CFI data
1129 says. Sigh.
1130
1131 Why is this important? Imagine that a wrapper has a stack
1132 allocated local, and passes to the hidden call, a pointer to it.
1133 Because gcc does not know about the hidden call, it may allocate
1134 that local in the redzone. Unfortunately the hidden call may then
1135 trash it before it comes to use it. So we must step clear of the
1136 redzone, for the duration of the hidden call, to make it safe.
1137
1138 Probably the same problem afflicts the other redzone-style ABIs too
1139 (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
1140 self describing (none of this CFI nonsense) so at least messing
1141 with the stack pointer doesn't give a danger of non-unwindable
1142 stack. */
1143
sewardjc8858442006-01-20 15:17:20 +00001144#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001145 do { \
sewardjc8858442006-01-20 15:17:20 +00001146 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001147 volatile unsigned long _argvec[1]; \
1148 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001149 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001150 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001151 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001152 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1153 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001154 "addq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001155 : /*out*/ "=a" (_res) \
1156 : /*in*/ "a" (&_argvec[0]) \
1157 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1158 ); \
1159 lval = (__typeof__(lval)) _res; \
1160 } while (0)
1161
sewardjc8858442006-01-20 15:17:20 +00001162#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001163 do { \
sewardjc8858442006-01-20 15:17:20 +00001164 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001165 volatile unsigned long _argvec[2]; \
1166 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001167 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001168 _argvec[1] = (unsigned long)(arg1); \
1169 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001170 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001171 "movq 8(%%rax), %%rdi\n\t" \
1172 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1173 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001174 "addq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001175 : /*out*/ "=a" (_res) \
1176 : /*in*/ "a" (&_argvec[0]) \
1177 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1178 ); \
1179 lval = (__typeof__(lval)) _res; \
1180 } while (0)
1181
sewardjc8858442006-01-20 15:17:20 +00001182#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001183 do { \
sewardjc8858442006-01-20 15:17:20 +00001184 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001185 volatile unsigned long _argvec[3]; \
1186 volatile unsigned long _res; \
sewardjc8858442006-01-20 15:17:20 +00001187 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001188 _argvec[1] = (unsigned long)(arg1); \
1189 _argvec[2] = (unsigned long)(arg2); \
1190 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001191 "subq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001192 "movq 16(%%rax), %%rsi\n\t" \
1193 "movq 8(%%rax), %%rdi\n\t" \
1194 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1195 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001196 "addq $128,%%rsp\n\t" \
sewardj0ec07f32006-01-12 12:32:32 +00001197 : /*out*/ "=a" (_res) \
1198 : /*in*/ "a" (&_argvec[0]) \
1199 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1200 ); \
1201 lval = (__typeof__(lval)) _res; \
1202 } while (0)
1203
sewardja50f9dc2006-03-11 16:19:14 +00001204#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1205 do { \
1206 volatile OrigFn _orig = (orig); \
1207 volatile unsigned long _argvec[4]; \
1208 volatile unsigned long _res; \
1209 _argvec[0] = (unsigned long)_orig.nraddr; \
1210 _argvec[1] = (unsigned long)(arg1); \
1211 _argvec[2] = (unsigned long)(arg2); \
1212 _argvec[3] = (unsigned long)(arg3); \
1213 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001214 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001215 "movq 24(%%rax), %%rdx\n\t" \
1216 "movq 16(%%rax), %%rsi\n\t" \
1217 "movq 8(%%rax), %%rdi\n\t" \
1218 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1219 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001220 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001221 : /*out*/ "=a" (_res) \
1222 : /*in*/ "a" (&_argvec[0]) \
1223 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1224 ); \
1225 lval = (__typeof__(lval)) _res; \
1226 } while (0)
1227
1228#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1229 do { \
1230 volatile OrigFn _orig = (orig); \
1231 volatile unsigned long _argvec[5]; \
1232 volatile unsigned long _res; \
1233 _argvec[0] = (unsigned long)_orig.nraddr; \
1234 _argvec[1] = (unsigned long)(arg1); \
1235 _argvec[2] = (unsigned long)(arg2); \
1236 _argvec[3] = (unsigned long)(arg3); \
1237 _argvec[4] = (unsigned long)(arg4); \
1238 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001239 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001240 "movq 32(%%rax), %%rcx\n\t" \
1241 "movq 24(%%rax), %%rdx\n\t" \
1242 "movq 16(%%rax), %%rsi\n\t" \
1243 "movq 8(%%rax), %%rdi\n\t" \
1244 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1245 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001246 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001247 : /*out*/ "=a" (_res) \
1248 : /*in*/ "a" (&_argvec[0]) \
1249 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1250 ); \
1251 lval = (__typeof__(lval)) _res; \
1252 } while (0)
1253
1254#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1255 do { \
1256 volatile OrigFn _orig = (orig); \
1257 volatile unsigned long _argvec[6]; \
1258 volatile unsigned long _res; \
1259 _argvec[0] = (unsigned long)_orig.nraddr; \
1260 _argvec[1] = (unsigned long)(arg1); \
1261 _argvec[2] = (unsigned long)(arg2); \
1262 _argvec[3] = (unsigned long)(arg3); \
1263 _argvec[4] = (unsigned long)(arg4); \
1264 _argvec[5] = (unsigned long)(arg5); \
1265 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001266 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001267 "movq 40(%%rax), %%r8\n\t" \
1268 "movq 32(%%rax), %%rcx\n\t" \
1269 "movq 24(%%rax), %%rdx\n\t" \
1270 "movq 16(%%rax), %%rsi\n\t" \
1271 "movq 8(%%rax), %%rdi\n\t" \
1272 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1273 VALGRIND_CALL_NOREDIR_RAX \
sewardja07c2e12007-11-09 23:09:50 +00001274 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001275 : /*out*/ "=a" (_res) \
1276 : /*in*/ "a" (&_argvec[0]) \
1277 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1278 ); \
1279 lval = (__typeof__(lval)) _res; \
1280 } while (0)
1281
1282#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1283 do { \
1284 volatile OrigFn _orig = (orig); \
1285 volatile unsigned long _argvec[7]; \
1286 volatile unsigned long _res; \
1287 _argvec[0] = (unsigned long)_orig.nraddr; \
1288 _argvec[1] = (unsigned long)(arg1); \
1289 _argvec[2] = (unsigned long)(arg2); \
1290 _argvec[3] = (unsigned long)(arg3); \
1291 _argvec[4] = (unsigned long)(arg4); \
1292 _argvec[5] = (unsigned long)(arg5); \
1293 _argvec[6] = (unsigned long)(arg6); \
1294 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001295 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001296 "movq 48(%%rax), %%r9\n\t" \
1297 "movq 40(%%rax), %%r8\n\t" \
1298 "movq 32(%%rax), %%rcx\n\t" \
1299 "movq 24(%%rax), %%rdx\n\t" \
1300 "movq 16(%%rax), %%rsi\n\t" \
1301 "movq 8(%%rax), %%rdi\n\t" \
1302 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
sewardja07c2e12007-11-09 23:09:50 +00001303 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001304 VALGRIND_CALL_NOREDIR_RAX \
1305 : /*out*/ "=a" (_res) \
1306 : /*in*/ "a" (&_argvec[0]) \
1307 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1308 ); \
1309 lval = (__typeof__(lval)) _res; \
1310 } while (0)
1311
1312#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1313 arg7) \
1314 do { \
1315 volatile OrigFn _orig = (orig); \
1316 volatile unsigned long _argvec[8]; \
1317 volatile unsigned long _res; \
1318 _argvec[0] = (unsigned long)_orig.nraddr; \
1319 _argvec[1] = (unsigned long)(arg1); \
1320 _argvec[2] = (unsigned long)(arg2); \
1321 _argvec[3] = (unsigned long)(arg3); \
1322 _argvec[4] = (unsigned long)(arg4); \
1323 _argvec[5] = (unsigned long)(arg5); \
1324 _argvec[6] = (unsigned long)(arg6); \
1325 _argvec[7] = (unsigned long)(arg7); \
1326 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001327 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001328 "pushq 56(%%rax)\n\t" \
1329 "movq 48(%%rax), %%r9\n\t" \
1330 "movq 40(%%rax), %%r8\n\t" \
1331 "movq 32(%%rax), %%rcx\n\t" \
1332 "movq 24(%%rax), %%rdx\n\t" \
1333 "movq 16(%%rax), %%rsi\n\t" \
1334 "movq 8(%%rax), %%rdi\n\t" \
1335 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1336 VALGRIND_CALL_NOREDIR_RAX \
1337 "addq $8, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001338 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001339 : /*out*/ "=a" (_res) \
1340 : /*in*/ "a" (&_argvec[0]) \
1341 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1342 ); \
1343 lval = (__typeof__(lval)) _res; \
1344 } while (0)
1345
1346#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1347 arg7,arg8) \
1348 do { \
1349 volatile OrigFn _orig = (orig); \
1350 volatile unsigned long _argvec[9]; \
1351 volatile unsigned long _res; \
1352 _argvec[0] = (unsigned long)_orig.nraddr; \
1353 _argvec[1] = (unsigned long)(arg1); \
1354 _argvec[2] = (unsigned long)(arg2); \
1355 _argvec[3] = (unsigned long)(arg3); \
1356 _argvec[4] = (unsigned long)(arg4); \
1357 _argvec[5] = (unsigned long)(arg5); \
1358 _argvec[6] = (unsigned long)(arg6); \
1359 _argvec[7] = (unsigned long)(arg7); \
1360 _argvec[8] = (unsigned long)(arg8); \
1361 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001362 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001363 "pushq 64(%%rax)\n\t" \
1364 "pushq 56(%%rax)\n\t" \
1365 "movq 48(%%rax), %%r9\n\t" \
1366 "movq 40(%%rax), %%r8\n\t" \
1367 "movq 32(%%rax), %%rcx\n\t" \
1368 "movq 24(%%rax), %%rdx\n\t" \
1369 "movq 16(%%rax), %%rsi\n\t" \
1370 "movq 8(%%rax), %%rdi\n\t" \
1371 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1372 VALGRIND_CALL_NOREDIR_RAX \
1373 "addq $16, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001374 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001375 : /*out*/ "=a" (_res) \
1376 : /*in*/ "a" (&_argvec[0]) \
1377 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1378 ); \
1379 lval = (__typeof__(lval)) _res; \
1380 } while (0)
1381
1382#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1383 arg7,arg8,arg9) \
1384 do { \
1385 volatile OrigFn _orig = (orig); \
1386 volatile unsigned long _argvec[10]; \
1387 volatile unsigned long _res; \
1388 _argvec[0] = (unsigned long)_orig.nraddr; \
1389 _argvec[1] = (unsigned long)(arg1); \
1390 _argvec[2] = (unsigned long)(arg2); \
1391 _argvec[3] = (unsigned long)(arg3); \
1392 _argvec[4] = (unsigned long)(arg4); \
1393 _argvec[5] = (unsigned long)(arg5); \
1394 _argvec[6] = (unsigned long)(arg6); \
1395 _argvec[7] = (unsigned long)(arg7); \
1396 _argvec[8] = (unsigned long)(arg8); \
1397 _argvec[9] = (unsigned long)(arg9); \
1398 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001399 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001400 "pushq 72(%%rax)\n\t" \
1401 "pushq 64(%%rax)\n\t" \
1402 "pushq 56(%%rax)\n\t" \
1403 "movq 48(%%rax), %%r9\n\t" \
1404 "movq 40(%%rax), %%r8\n\t" \
1405 "movq 32(%%rax), %%rcx\n\t" \
1406 "movq 24(%%rax), %%rdx\n\t" \
1407 "movq 16(%%rax), %%rsi\n\t" \
1408 "movq 8(%%rax), %%rdi\n\t" \
1409 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1410 VALGRIND_CALL_NOREDIR_RAX \
1411 "addq $24, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001412 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001413 : /*out*/ "=a" (_res) \
1414 : /*in*/ "a" (&_argvec[0]) \
1415 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1416 ); \
1417 lval = (__typeof__(lval)) _res; \
1418 } while (0)
1419
1420#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1421 arg7,arg8,arg9,arg10) \
1422 do { \
1423 volatile OrigFn _orig = (orig); \
1424 volatile unsigned long _argvec[11]; \
1425 volatile unsigned long _res; \
1426 _argvec[0] = (unsigned long)_orig.nraddr; \
1427 _argvec[1] = (unsigned long)(arg1); \
1428 _argvec[2] = (unsigned long)(arg2); \
1429 _argvec[3] = (unsigned long)(arg3); \
1430 _argvec[4] = (unsigned long)(arg4); \
1431 _argvec[5] = (unsigned long)(arg5); \
1432 _argvec[6] = (unsigned long)(arg6); \
1433 _argvec[7] = (unsigned long)(arg7); \
1434 _argvec[8] = (unsigned long)(arg8); \
1435 _argvec[9] = (unsigned long)(arg9); \
1436 _argvec[10] = (unsigned long)(arg10); \
1437 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001438 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001439 "pushq 80(%%rax)\n\t" \
1440 "pushq 72(%%rax)\n\t" \
1441 "pushq 64(%%rax)\n\t" \
1442 "pushq 56(%%rax)\n\t" \
1443 "movq 48(%%rax), %%r9\n\t" \
1444 "movq 40(%%rax), %%r8\n\t" \
1445 "movq 32(%%rax), %%rcx\n\t" \
1446 "movq 24(%%rax), %%rdx\n\t" \
1447 "movq 16(%%rax), %%rsi\n\t" \
1448 "movq 8(%%rax), %%rdi\n\t" \
1449 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1450 VALGRIND_CALL_NOREDIR_RAX \
1451 "addq $32, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001452 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001453 : /*out*/ "=a" (_res) \
1454 : /*in*/ "a" (&_argvec[0]) \
1455 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1456 ); \
1457 lval = (__typeof__(lval)) _res; \
1458 } while (0)
1459
1460#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1461 arg7,arg8,arg9,arg10,arg11) \
1462 do { \
1463 volatile OrigFn _orig = (orig); \
1464 volatile unsigned long _argvec[12]; \
1465 volatile unsigned long _res; \
1466 _argvec[0] = (unsigned long)_orig.nraddr; \
1467 _argvec[1] = (unsigned long)(arg1); \
1468 _argvec[2] = (unsigned long)(arg2); \
1469 _argvec[3] = (unsigned long)(arg3); \
1470 _argvec[4] = (unsigned long)(arg4); \
1471 _argvec[5] = (unsigned long)(arg5); \
1472 _argvec[6] = (unsigned long)(arg6); \
1473 _argvec[7] = (unsigned long)(arg7); \
1474 _argvec[8] = (unsigned long)(arg8); \
1475 _argvec[9] = (unsigned long)(arg9); \
1476 _argvec[10] = (unsigned long)(arg10); \
1477 _argvec[11] = (unsigned long)(arg11); \
1478 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001479 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001480 "pushq 88(%%rax)\n\t" \
1481 "pushq 80(%%rax)\n\t" \
1482 "pushq 72(%%rax)\n\t" \
1483 "pushq 64(%%rax)\n\t" \
1484 "pushq 56(%%rax)\n\t" \
1485 "movq 48(%%rax), %%r9\n\t" \
1486 "movq 40(%%rax), %%r8\n\t" \
1487 "movq 32(%%rax), %%rcx\n\t" \
1488 "movq 24(%%rax), %%rdx\n\t" \
1489 "movq 16(%%rax), %%rsi\n\t" \
1490 "movq 8(%%rax), %%rdi\n\t" \
1491 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1492 VALGRIND_CALL_NOREDIR_RAX \
1493 "addq $40, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001494 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001495 : /*out*/ "=a" (_res) \
1496 : /*in*/ "a" (&_argvec[0]) \
1497 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1498 ); \
1499 lval = (__typeof__(lval)) _res; \
1500 } while (0)
1501
1502#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1503 arg7,arg8,arg9,arg10,arg11,arg12) \
1504 do { \
1505 volatile OrigFn _orig = (orig); \
1506 volatile unsigned long _argvec[13]; \
1507 volatile unsigned long _res; \
1508 _argvec[0] = (unsigned long)_orig.nraddr; \
1509 _argvec[1] = (unsigned long)(arg1); \
1510 _argvec[2] = (unsigned long)(arg2); \
1511 _argvec[3] = (unsigned long)(arg3); \
1512 _argvec[4] = (unsigned long)(arg4); \
1513 _argvec[5] = (unsigned long)(arg5); \
1514 _argvec[6] = (unsigned long)(arg6); \
1515 _argvec[7] = (unsigned long)(arg7); \
1516 _argvec[8] = (unsigned long)(arg8); \
1517 _argvec[9] = (unsigned long)(arg9); \
1518 _argvec[10] = (unsigned long)(arg10); \
1519 _argvec[11] = (unsigned long)(arg11); \
1520 _argvec[12] = (unsigned long)(arg12); \
1521 __asm__ volatile( \
sewardja07c2e12007-11-09 23:09:50 +00001522 "subq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001523 "pushq 96(%%rax)\n\t" \
1524 "pushq 88(%%rax)\n\t" \
1525 "pushq 80(%%rax)\n\t" \
1526 "pushq 72(%%rax)\n\t" \
1527 "pushq 64(%%rax)\n\t" \
1528 "pushq 56(%%rax)\n\t" \
1529 "movq 48(%%rax), %%r9\n\t" \
1530 "movq 40(%%rax), %%r8\n\t" \
1531 "movq 32(%%rax), %%rcx\n\t" \
1532 "movq 24(%%rax), %%rdx\n\t" \
1533 "movq 16(%%rax), %%rsi\n\t" \
1534 "movq 8(%%rax), %%rdi\n\t" \
1535 "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1536 VALGRIND_CALL_NOREDIR_RAX \
1537 "addq $48, %%rsp\n" \
sewardja07c2e12007-11-09 23:09:50 +00001538 "addq $128,%%rsp\n\t" \
sewardja50f9dc2006-03-11 16:19:14 +00001539 : /*out*/ "=a" (_res) \
1540 : /*in*/ "a" (&_argvec[0]) \
1541 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1542 ); \
1543 lval = (__typeof__(lval)) _res; \
1544 } while (0)
1545
njnf76d27a2009-05-28 01:53:07 +00001546#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
sewardj0ec07f32006-01-12 12:32:32 +00001547
sewardjf5c1a7f2006-10-17 01:32:48 +00001548/* ------------------------ ppc32-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00001549
sewardjf5c1a7f2006-10-17 01:32:48 +00001550#if defined(PLAT_ppc32_linux)
sewardj0ec07f32006-01-12 12:32:32 +00001551
sewardjead61df2006-03-12 13:39:15 +00001552/* This is useful for finding out about the on-stack stuff:
1553
1554 extern int f9 ( int,int,int,int,int,int,int,int,int );
1555 extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1556 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1557 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1558
1559 int g9 ( void ) {
1560 return f9(11,22,33,44,55,66,77,88,99);
1561 }
1562 int g10 ( void ) {
1563 return f10(11,22,33,44,55,66,77,88,99,110);
1564 }
1565 int g11 ( void ) {
1566 return f11(11,22,33,44,55,66,77,88,99,110,121);
1567 }
1568 int g12 ( void ) {
1569 return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1570 }
1571*/
1572
sewardj0ec07f32006-01-12 12:32:32 +00001573/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1574
1575/* These regs are trashed by the hidden call. */
sewardjead61df2006-03-12 13:39:15 +00001576#define __CALLER_SAVED_REGS \
1577 "lr", "ctr", "xer", \
1578 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1579 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1580 "r11", "r12", "r13"
sewardj0ec07f32006-01-12 12:32:32 +00001581
sewardjead61df2006-03-12 13:39:15 +00001582/* These CALL_FN_ macros assume that on ppc32-linux,
1583 sizeof(unsigned long) == 4. */
sewardj0ec07f32006-01-12 12:32:32 +00001584
sewardj38de0992006-01-20 16:46:34 +00001585#define CALL_FN_W_v(lval, orig) \
sewardj0ec07f32006-01-12 12:32:32 +00001586 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00001587 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001588 volatile unsigned long _argvec[1]; \
1589 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00001590 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001591 __asm__ volatile( \
1592 "mr 11,%1\n\t" \
1593 "lwz 11,0(11)\n\t" /* target->r11 */ \
1594 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1595 "mr %0,3" \
1596 : /*out*/ "=r" (_res) \
1597 : /*in*/ "r" (&_argvec[0]) \
1598 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1599 ); \
1600 lval = (__typeof__(lval)) _res; \
1601 } while (0)
1602
sewardj38de0992006-01-20 16:46:34 +00001603#define CALL_FN_W_W(lval, orig, arg1) \
sewardj0ec07f32006-01-12 12:32:32 +00001604 do { \
sewardj38de0992006-01-20 16:46:34 +00001605 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001606 volatile unsigned long _argvec[2]; \
1607 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001608 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001609 _argvec[1] = (unsigned long)arg1; \
1610 __asm__ volatile( \
1611 "mr 11,%1\n\t" \
1612 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1613 "lwz 11,0(11)\n\t" /* target->r11 */ \
1614 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1615 "mr %0,3" \
1616 : /*out*/ "=r" (_res) \
1617 : /*in*/ "r" (&_argvec[0]) \
1618 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1619 ); \
1620 lval = (__typeof__(lval)) _res; \
1621 } while (0)
1622
sewardj38de0992006-01-20 16:46:34 +00001623#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj0ec07f32006-01-12 12:32:32 +00001624 do { \
sewardj38de0992006-01-20 16:46:34 +00001625 volatile OrigFn _orig = (orig); \
sewardj0ec07f32006-01-12 12:32:32 +00001626 volatile unsigned long _argvec[3]; \
1627 volatile unsigned long _res; \
sewardj38de0992006-01-20 16:46:34 +00001628 _argvec[0] = (unsigned long)_orig.nraddr; \
sewardj0ec07f32006-01-12 12:32:32 +00001629 _argvec[1] = (unsigned long)arg1; \
1630 _argvec[2] = (unsigned long)arg2; \
1631 __asm__ volatile( \
1632 "mr 11,%1\n\t" \
1633 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1634 "lwz 4,8(11)\n\t" \
1635 "lwz 11,0(11)\n\t" /* target->r11 */ \
1636 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1637 "mr %0,3" \
1638 : /*out*/ "=r" (_res) \
1639 : /*in*/ "r" (&_argvec[0]) \
1640 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1641 ); \
1642 lval = (__typeof__(lval)) _res; \
1643 } while (0)
1644
sewardjead61df2006-03-12 13:39:15 +00001645#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1646 do { \
1647 volatile OrigFn _orig = (orig); \
1648 volatile unsigned long _argvec[4]; \
1649 volatile unsigned long _res; \
1650 _argvec[0] = (unsigned long)_orig.nraddr; \
1651 _argvec[1] = (unsigned long)arg1; \
1652 _argvec[2] = (unsigned long)arg2; \
1653 _argvec[3] = (unsigned long)arg3; \
1654 __asm__ volatile( \
1655 "mr 11,%1\n\t" \
1656 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1657 "lwz 4,8(11)\n\t" \
1658 "lwz 5,12(11)\n\t" \
1659 "lwz 11,0(11)\n\t" /* target->r11 */ \
1660 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1661 "mr %0,3" \
1662 : /*out*/ "=r" (_res) \
1663 : /*in*/ "r" (&_argvec[0]) \
1664 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1665 ); \
1666 lval = (__typeof__(lval)) _res; \
1667 } while (0)
1668
1669#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1670 do { \
1671 volatile OrigFn _orig = (orig); \
1672 volatile unsigned long _argvec[5]; \
1673 volatile unsigned long _res; \
1674 _argvec[0] = (unsigned long)_orig.nraddr; \
1675 _argvec[1] = (unsigned long)arg1; \
1676 _argvec[2] = (unsigned long)arg2; \
1677 _argvec[3] = (unsigned long)arg3; \
1678 _argvec[4] = (unsigned long)arg4; \
1679 __asm__ volatile( \
1680 "mr 11,%1\n\t" \
1681 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1682 "lwz 4,8(11)\n\t" \
1683 "lwz 5,12(11)\n\t" \
1684 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1685 "lwz 11,0(11)\n\t" /* target->r11 */ \
1686 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1687 "mr %0,3" \
1688 : /*out*/ "=r" (_res) \
1689 : /*in*/ "r" (&_argvec[0]) \
1690 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1691 ); \
1692 lval = (__typeof__(lval)) _res; \
1693 } while (0)
1694
1695#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1696 do { \
1697 volatile OrigFn _orig = (orig); \
1698 volatile unsigned long _argvec[6]; \
1699 volatile unsigned long _res; \
1700 _argvec[0] = (unsigned long)_orig.nraddr; \
1701 _argvec[1] = (unsigned long)arg1; \
1702 _argvec[2] = (unsigned long)arg2; \
1703 _argvec[3] = (unsigned long)arg3; \
1704 _argvec[4] = (unsigned long)arg4; \
1705 _argvec[5] = (unsigned long)arg5; \
1706 __asm__ volatile( \
1707 "mr 11,%1\n\t" \
1708 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1709 "lwz 4,8(11)\n\t" \
1710 "lwz 5,12(11)\n\t" \
1711 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1712 "lwz 7,20(11)\n\t" \
1713 "lwz 11,0(11)\n\t" /* target->r11 */ \
1714 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1715 "mr %0,3" \
1716 : /*out*/ "=r" (_res) \
1717 : /*in*/ "r" (&_argvec[0]) \
1718 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1719 ); \
1720 lval = (__typeof__(lval)) _res; \
1721 } while (0)
1722
1723#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1724 do { \
1725 volatile OrigFn _orig = (orig); \
1726 volatile unsigned long _argvec[7]; \
1727 volatile unsigned long _res; \
1728 _argvec[0] = (unsigned long)_orig.nraddr; \
1729 _argvec[1] = (unsigned long)arg1; \
1730 _argvec[2] = (unsigned long)arg2; \
1731 _argvec[3] = (unsigned long)arg3; \
1732 _argvec[4] = (unsigned long)arg4; \
1733 _argvec[5] = (unsigned long)arg5; \
1734 _argvec[6] = (unsigned long)arg6; \
1735 __asm__ volatile( \
1736 "mr 11,%1\n\t" \
1737 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1738 "lwz 4,8(11)\n\t" \
1739 "lwz 5,12(11)\n\t" \
1740 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1741 "lwz 7,20(11)\n\t" \
1742 "lwz 8,24(11)\n\t" \
1743 "lwz 11,0(11)\n\t" /* target->r11 */ \
1744 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1745 "mr %0,3" \
1746 : /*out*/ "=r" (_res) \
1747 : /*in*/ "r" (&_argvec[0]) \
1748 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1749 ); \
1750 lval = (__typeof__(lval)) _res; \
1751 } while (0)
1752
1753#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1754 arg7) \
1755 do { \
1756 volatile OrigFn _orig = (orig); \
1757 volatile unsigned long _argvec[8]; \
1758 volatile unsigned long _res; \
1759 _argvec[0] = (unsigned long)_orig.nraddr; \
1760 _argvec[1] = (unsigned long)arg1; \
1761 _argvec[2] = (unsigned long)arg2; \
1762 _argvec[3] = (unsigned long)arg3; \
1763 _argvec[4] = (unsigned long)arg4; \
1764 _argvec[5] = (unsigned long)arg5; \
1765 _argvec[6] = (unsigned long)arg6; \
1766 _argvec[7] = (unsigned long)arg7; \
1767 __asm__ volatile( \
1768 "mr 11,%1\n\t" \
1769 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1770 "lwz 4,8(11)\n\t" \
1771 "lwz 5,12(11)\n\t" \
1772 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1773 "lwz 7,20(11)\n\t" \
1774 "lwz 8,24(11)\n\t" \
1775 "lwz 9,28(11)\n\t" \
1776 "lwz 11,0(11)\n\t" /* target->r11 */ \
1777 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1778 "mr %0,3" \
1779 : /*out*/ "=r" (_res) \
1780 : /*in*/ "r" (&_argvec[0]) \
1781 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1782 ); \
1783 lval = (__typeof__(lval)) _res; \
1784 } while (0)
1785
1786#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1787 arg7,arg8) \
1788 do { \
1789 volatile OrigFn _orig = (orig); \
1790 volatile unsigned long _argvec[9]; \
1791 volatile unsigned long _res; \
1792 _argvec[0] = (unsigned long)_orig.nraddr; \
1793 _argvec[1] = (unsigned long)arg1; \
1794 _argvec[2] = (unsigned long)arg2; \
1795 _argvec[3] = (unsigned long)arg3; \
1796 _argvec[4] = (unsigned long)arg4; \
1797 _argvec[5] = (unsigned long)arg5; \
1798 _argvec[6] = (unsigned long)arg6; \
1799 _argvec[7] = (unsigned long)arg7; \
1800 _argvec[8] = (unsigned long)arg8; \
1801 __asm__ volatile( \
1802 "mr 11,%1\n\t" \
1803 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1804 "lwz 4,8(11)\n\t" \
1805 "lwz 5,12(11)\n\t" \
1806 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1807 "lwz 7,20(11)\n\t" \
1808 "lwz 8,24(11)\n\t" \
1809 "lwz 9,28(11)\n\t" \
1810 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1811 "lwz 11,0(11)\n\t" /* target->r11 */ \
1812 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1813 "mr %0,3" \
1814 : /*out*/ "=r" (_res) \
1815 : /*in*/ "r" (&_argvec[0]) \
1816 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1817 ); \
1818 lval = (__typeof__(lval)) _res; \
1819 } while (0)
1820
1821#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1822 arg7,arg8,arg9) \
1823 do { \
1824 volatile OrigFn _orig = (orig); \
1825 volatile unsigned long _argvec[10]; \
1826 volatile unsigned long _res; \
1827 _argvec[0] = (unsigned long)_orig.nraddr; \
1828 _argvec[1] = (unsigned long)arg1; \
1829 _argvec[2] = (unsigned long)arg2; \
1830 _argvec[3] = (unsigned long)arg3; \
1831 _argvec[4] = (unsigned long)arg4; \
1832 _argvec[5] = (unsigned long)arg5; \
1833 _argvec[6] = (unsigned long)arg6; \
1834 _argvec[7] = (unsigned long)arg7; \
1835 _argvec[8] = (unsigned long)arg8; \
1836 _argvec[9] = (unsigned long)arg9; \
1837 __asm__ volatile( \
1838 "mr 11,%1\n\t" \
1839 "addi 1,1,-16\n\t" \
1840 /* arg9 */ \
1841 "lwz 3,36(11)\n\t" \
1842 "stw 3,8(1)\n\t" \
1843 /* args1-8 */ \
1844 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1845 "lwz 4,8(11)\n\t" \
1846 "lwz 5,12(11)\n\t" \
1847 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1848 "lwz 7,20(11)\n\t" \
1849 "lwz 8,24(11)\n\t" \
1850 "lwz 9,28(11)\n\t" \
1851 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1852 "lwz 11,0(11)\n\t" /* target->r11 */ \
1853 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1854 "addi 1,1,16\n\t" \
1855 "mr %0,3" \
1856 : /*out*/ "=r" (_res) \
1857 : /*in*/ "r" (&_argvec[0]) \
1858 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1859 ); \
1860 lval = (__typeof__(lval)) _res; \
1861 } while (0)
1862
1863#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1864 arg7,arg8,arg9,arg10) \
1865 do { \
1866 volatile OrigFn _orig = (orig); \
1867 volatile unsigned long _argvec[11]; \
1868 volatile unsigned long _res; \
1869 _argvec[0] = (unsigned long)_orig.nraddr; \
1870 _argvec[1] = (unsigned long)arg1; \
1871 _argvec[2] = (unsigned long)arg2; \
1872 _argvec[3] = (unsigned long)arg3; \
1873 _argvec[4] = (unsigned long)arg4; \
1874 _argvec[5] = (unsigned long)arg5; \
1875 _argvec[6] = (unsigned long)arg6; \
1876 _argvec[7] = (unsigned long)arg7; \
1877 _argvec[8] = (unsigned long)arg8; \
1878 _argvec[9] = (unsigned long)arg9; \
1879 _argvec[10] = (unsigned long)arg10; \
1880 __asm__ volatile( \
1881 "mr 11,%1\n\t" \
1882 "addi 1,1,-16\n\t" \
1883 /* arg10 */ \
1884 "lwz 3,40(11)\n\t" \
1885 "stw 3,12(1)\n\t" \
1886 /* arg9 */ \
1887 "lwz 3,36(11)\n\t" \
1888 "stw 3,8(1)\n\t" \
1889 /* args1-8 */ \
1890 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1891 "lwz 4,8(11)\n\t" \
1892 "lwz 5,12(11)\n\t" \
1893 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1894 "lwz 7,20(11)\n\t" \
1895 "lwz 8,24(11)\n\t" \
1896 "lwz 9,28(11)\n\t" \
1897 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1898 "lwz 11,0(11)\n\t" /* target->r11 */ \
1899 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1900 "addi 1,1,16\n\t" \
1901 "mr %0,3" \
1902 : /*out*/ "=r" (_res) \
1903 : /*in*/ "r" (&_argvec[0]) \
1904 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1905 ); \
1906 lval = (__typeof__(lval)) _res; \
1907 } while (0)
1908
1909#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1910 arg7,arg8,arg9,arg10,arg11) \
1911 do { \
1912 volatile OrigFn _orig = (orig); \
1913 volatile unsigned long _argvec[12]; \
1914 volatile unsigned long _res; \
1915 _argvec[0] = (unsigned long)_orig.nraddr; \
1916 _argvec[1] = (unsigned long)arg1; \
1917 _argvec[2] = (unsigned long)arg2; \
1918 _argvec[3] = (unsigned long)arg3; \
1919 _argvec[4] = (unsigned long)arg4; \
1920 _argvec[5] = (unsigned long)arg5; \
1921 _argvec[6] = (unsigned long)arg6; \
1922 _argvec[7] = (unsigned long)arg7; \
1923 _argvec[8] = (unsigned long)arg8; \
1924 _argvec[9] = (unsigned long)arg9; \
1925 _argvec[10] = (unsigned long)arg10; \
1926 _argvec[11] = (unsigned long)arg11; \
1927 __asm__ volatile( \
1928 "mr 11,%1\n\t" \
1929 "addi 1,1,-32\n\t" \
1930 /* arg11 */ \
1931 "lwz 3,44(11)\n\t" \
1932 "stw 3,16(1)\n\t" \
1933 /* arg10 */ \
1934 "lwz 3,40(11)\n\t" \
1935 "stw 3,12(1)\n\t" \
1936 /* arg9 */ \
1937 "lwz 3,36(11)\n\t" \
1938 "stw 3,8(1)\n\t" \
1939 /* args1-8 */ \
1940 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1941 "lwz 4,8(11)\n\t" \
1942 "lwz 5,12(11)\n\t" \
1943 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1944 "lwz 7,20(11)\n\t" \
1945 "lwz 8,24(11)\n\t" \
1946 "lwz 9,28(11)\n\t" \
1947 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1948 "lwz 11,0(11)\n\t" /* target->r11 */ \
1949 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1950 "addi 1,1,32\n\t" \
1951 "mr %0,3" \
1952 : /*out*/ "=r" (_res) \
1953 : /*in*/ "r" (&_argvec[0]) \
1954 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1955 ); \
1956 lval = (__typeof__(lval)) _res; \
1957 } while (0)
1958
1959#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1960 arg7,arg8,arg9,arg10,arg11,arg12) \
1961 do { \
1962 volatile OrigFn _orig = (orig); \
1963 volatile unsigned long _argvec[13]; \
1964 volatile unsigned long _res; \
1965 _argvec[0] = (unsigned long)_orig.nraddr; \
1966 _argvec[1] = (unsigned long)arg1; \
1967 _argvec[2] = (unsigned long)arg2; \
1968 _argvec[3] = (unsigned long)arg3; \
1969 _argvec[4] = (unsigned long)arg4; \
1970 _argvec[5] = (unsigned long)arg5; \
1971 _argvec[6] = (unsigned long)arg6; \
1972 _argvec[7] = (unsigned long)arg7; \
1973 _argvec[8] = (unsigned long)arg8; \
1974 _argvec[9] = (unsigned long)arg9; \
1975 _argvec[10] = (unsigned long)arg10; \
1976 _argvec[11] = (unsigned long)arg11; \
1977 _argvec[12] = (unsigned long)arg12; \
1978 __asm__ volatile( \
1979 "mr 11,%1\n\t" \
1980 "addi 1,1,-32\n\t" \
1981 /* arg12 */ \
1982 "lwz 3,48(11)\n\t" \
1983 "stw 3,20(1)\n\t" \
1984 /* arg11 */ \
1985 "lwz 3,44(11)\n\t" \
1986 "stw 3,16(1)\n\t" \
1987 /* arg10 */ \
1988 "lwz 3,40(11)\n\t" \
1989 "stw 3,12(1)\n\t" \
1990 /* arg9 */ \
1991 "lwz 3,36(11)\n\t" \
1992 "stw 3,8(1)\n\t" \
1993 /* args1-8 */ \
1994 "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1995 "lwz 4,8(11)\n\t" \
1996 "lwz 5,12(11)\n\t" \
1997 "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1998 "lwz 7,20(11)\n\t" \
1999 "lwz 8,24(11)\n\t" \
2000 "lwz 9,28(11)\n\t" \
2001 "lwz 10,32(11)\n\t" /* arg8->r10 */ \
2002 "lwz 11,0(11)\n\t" /* target->r11 */ \
2003 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2004 "addi 1,1,32\n\t" \
2005 "mr %0,3" \
2006 : /*out*/ "=r" (_res) \
2007 : /*in*/ "r" (&_argvec[0]) \
2008 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2009 ); \
2010 lval = (__typeof__(lval)) _res; \
2011 } while (0)
2012
sewardjf5c1a7f2006-10-17 01:32:48 +00002013#endif /* PLAT_ppc32_linux */
sewardj0ec07f32006-01-12 12:32:32 +00002014
sewardjf5c1a7f2006-10-17 01:32:48 +00002015/* ------------------------ ppc64-linux ------------------------ */
sewardj0ec07f32006-01-12 12:32:32 +00002016
sewardjf5c1a7f2006-10-17 01:32:48 +00002017#if defined(PLAT_ppc64_linux)
sewardj9734b202006-01-17 01:49:37 +00002018
2019/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2020
2021/* These regs are trashed by the hidden call. */
sewardjcd636392006-03-12 16:48:14 +00002022#define __CALLER_SAVED_REGS \
2023 "lr", "ctr", "xer", \
2024 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2025 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2026 "r11", "r12", "r13"
sewardj9734b202006-01-17 01:49:37 +00002027
2028/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2029 long) == 8. */
2030
sewardjd68ac3e2006-01-20 14:31:57 +00002031#define CALL_FN_W_v(lval, orig) \
sewardj9734b202006-01-17 01:49:37 +00002032 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002033 volatile OrigFn _orig = (orig); \
2034 volatile unsigned long _argvec[3+0]; \
sewardj9734b202006-01-17 01:49:37 +00002035 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002036 /* _argvec[0] holds current r2 across the call */ \
2037 _argvec[1] = (unsigned long)_orig.r2; \
2038 _argvec[2] = (unsigned long)_orig.nraddr; \
sewardj9734b202006-01-17 01:49:37 +00002039 __asm__ volatile( \
2040 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002041 "std 2,-16(11)\n\t" /* save tocptr */ \
2042 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2043 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002044 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2045 "mr 11,%1\n\t" \
2046 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002047 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002048 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002049 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002050 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2051 ); \
2052 lval = (__typeof__(lval)) _res; \
2053 } while (0)
2054
sewardjd68ac3e2006-01-20 14:31:57 +00002055#define CALL_FN_W_W(lval, orig, arg1) \
sewardj9734b202006-01-17 01:49:37 +00002056 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002057 volatile OrigFn _orig = (orig); \
2058 volatile unsigned long _argvec[3+1]; \
sewardj9734b202006-01-17 01:49:37 +00002059 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002060 /* _argvec[0] holds current r2 across the call */ \
2061 _argvec[1] = (unsigned long)_orig.r2; \
2062 _argvec[2] = (unsigned long)_orig.nraddr; \
2063 _argvec[2+1] = (unsigned long)arg1; \
sewardj9734b202006-01-17 01:49:37 +00002064 __asm__ volatile( \
2065 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002066 "std 2,-16(11)\n\t" /* save tocptr */ \
2067 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2068 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2069 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002070 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2071 "mr 11,%1\n\t" \
2072 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002073 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002074 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002075 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002076 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2077 ); \
2078 lval = (__typeof__(lval)) _res; \
2079 } while (0)
2080
sewardjd68ac3e2006-01-20 14:31:57 +00002081#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
sewardj9734b202006-01-17 01:49:37 +00002082 do { \
sewardjd68ac3e2006-01-20 14:31:57 +00002083 volatile OrigFn _orig = (orig); \
2084 volatile unsigned long _argvec[3+2]; \
sewardj9734b202006-01-17 01:49:37 +00002085 volatile unsigned long _res; \
sewardjd68ac3e2006-01-20 14:31:57 +00002086 /* _argvec[0] holds current r2 across the call */ \
2087 _argvec[1] = (unsigned long)_orig.r2; \
2088 _argvec[2] = (unsigned long)_orig.nraddr; \
2089 _argvec[2+1] = (unsigned long)arg1; \
2090 _argvec[2+2] = (unsigned long)arg2; \
sewardj9734b202006-01-17 01:49:37 +00002091 __asm__ volatile( \
2092 "mr 11,%1\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002093 "std 2,-16(11)\n\t" /* save tocptr */ \
2094 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2095 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
sewardjcd636392006-03-12 16:48:14 +00002096 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
sewardjd68ac3e2006-01-20 14:31:57 +00002097 "ld 11, 0(11)\n\t" /* target->r11 */ \
sewardj9734b202006-01-17 01:49:37 +00002098 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2099 "mr 11,%1\n\t" \
2100 "mr %0,3\n\t" \
sewardjd68ac3e2006-01-20 14:31:57 +00002101 "ld 2,-16(11)" /* restore tocptr */ \
sewardj9734b202006-01-17 01:49:37 +00002102 : /*out*/ "=r" (_res) \
sewardjd68ac3e2006-01-20 14:31:57 +00002103 : /*in*/ "r" (&_argvec[2]) \
sewardj9734b202006-01-17 01:49:37 +00002104 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2105 ); \
2106 lval = (__typeof__(lval)) _res; \
2107 } while (0)
2108
sewardjcd636392006-03-12 16:48:14 +00002109#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2110 do { \
2111 volatile OrigFn _orig = (orig); \
2112 volatile unsigned long _argvec[3+3]; \
2113 volatile unsigned long _res; \
2114 /* _argvec[0] holds current r2 across the call */ \
2115 _argvec[1] = (unsigned long)_orig.r2; \
2116 _argvec[2] = (unsigned long)_orig.nraddr; \
2117 _argvec[2+1] = (unsigned long)arg1; \
2118 _argvec[2+2] = (unsigned long)arg2; \
2119 _argvec[2+3] = (unsigned long)arg3; \
2120 __asm__ volatile( \
2121 "mr 11,%1\n\t" \
2122 "std 2,-16(11)\n\t" /* save tocptr */ \
2123 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2124 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2125 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2126 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2127 "ld 11, 0(11)\n\t" /* target->r11 */ \
2128 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2129 "mr 11,%1\n\t" \
2130 "mr %0,3\n\t" \
2131 "ld 2,-16(11)" /* restore tocptr */ \
2132 : /*out*/ "=r" (_res) \
2133 : /*in*/ "r" (&_argvec[2]) \
2134 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2135 ); \
2136 lval = (__typeof__(lval)) _res; \
2137 } while (0)
2138
2139#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2140 do { \
2141 volatile OrigFn _orig = (orig); \
2142 volatile unsigned long _argvec[3+4]; \
2143 volatile unsigned long _res; \
2144 /* _argvec[0] holds current r2 across the call */ \
2145 _argvec[1] = (unsigned long)_orig.r2; \
2146 _argvec[2] = (unsigned long)_orig.nraddr; \
2147 _argvec[2+1] = (unsigned long)arg1; \
2148 _argvec[2+2] = (unsigned long)arg2; \
2149 _argvec[2+3] = (unsigned long)arg3; \
2150 _argvec[2+4] = (unsigned long)arg4; \
2151 __asm__ volatile( \
2152 "mr 11,%1\n\t" \
2153 "std 2,-16(11)\n\t" /* save tocptr */ \
2154 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2155 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2156 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2157 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2158 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2159 "ld 11, 0(11)\n\t" /* target->r11 */ \
2160 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2161 "mr 11,%1\n\t" \
2162 "mr %0,3\n\t" \
2163 "ld 2,-16(11)" /* restore tocptr */ \
2164 : /*out*/ "=r" (_res) \
2165 : /*in*/ "r" (&_argvec[2]) \
2166 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2167 ); \
2168 lval = (__typeof__(lval)) _res; \
2169 } while (0)
2170
2171#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2172 do { \
2173 volatile OrigFn _orig = (orig); \
2174 volatile unsigned long _argvec[3+5]; \
2175 volatile unsigned long _res; \
2176 /* _argvec[0] holds current r2 across the call */ \
2177 _argvec[1] = (unsigned long)_orig.r2; \
2178 _argvec[2] = (unsigned long)_orig.nraddr; \
2179 _argvec[2+1] = (unsigned long)arg1; \
2180 _argvec[2+2] = (unsigned long)arg2; \
2181 _argvec[2+3] = (unsigned long)arg3; \
2182 _argvec[2+4] = (unsigned long)arg4; \
2183 _argvec[2+5] = (unsigned long)arg5; \
2184 __asm__ volatile( \
2185 "mr 11,%1\n\t" \
2186 "std 2,-16(11)\n\t" /* save tocptr */ \
2187 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2188 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2189 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2190 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2191 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2192 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2193 "ld 11, 0(11)\n\t" /* target->r11 */ \
2194 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2195 "mr 11,%1\n\t" \
2196 "mr %0,3\n\t" \
2197 "ld 2,-16(11)" /* restore tocptr */ \
2198 : /*out*/ "=r" (_res) \
2199 : /*in*/ "r" (&_argvec[2]) \
2200 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2201 ); \
2202 lval = (__typeof__(lval)) _res; \
2203 } while (0)
2204
2205#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2206 do { \
2207 volatile OrigFn _orig = (orig); \
2208 volatile unsigned long _argvec[3+6]; \
2209 volatile unsigned long _res; \
2210 /* _argvec[0] holds current r2 across the call */ \
2211 _argvec[1] = (unsigned long)_orig.r2; \
2212 _argvec[2] = (unsigned long)_orig.nraddr; \
2213 _argvec[2+1] = (unsigned long)arg1; \
2214 _argvec[2+2] = (unsigned long)arg2; \
2215 _argvec[2+3] = (unsigned long)arg3; \
2216 _argvec[2+4] = (unsigned long)arg4; \
2217 _argvec[2+5] = (unsigned long)arg5; \
2218 _argvec[2+6] = (unsigned long)arg6; \
2219 __asm__ volatile( \
2220 "mr 11,%1\n\t" \
2221 "std 2,-16(11)\n\t" /* save tocptr */ \
2222 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2223 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2224 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2225 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2226 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2227 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2228 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2229 "ld 11, 0(11)\n\t" /* target->r11 */ \
2230 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2231 "mr 11,%1\n\t" \
2232 "mr %0,3\n\t" \
2233 "ld 2,-16(11)" /* restore tocptr */ \
2234 : /*out*/ "=r" (_res) \
2235 : /*in*/ "r" (&_argvec[2]) \
2236 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2237 ); \
2238 lval = (__typeof__(lval)) _res; \
2239 } while (0)
2240
2241#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2242 arg7) \
2243 do { \
2244 volatile OrigFn _orig = (orig); \
2245 volatile unsigned long _argvec[3+7]; \
2246 volatile unsigned long _res; \
2247 /* _argvec[0] holds current r2 across the call */ \
2248 _argvec[1] = (unsigned long)_orig.r2; \
2249 _argvec[2] = (unsigned long)_orig.nraddr; \
2250 _argvec[2+1] = (unsigned long)arg1; \
2251 _argvec[2+2] = (unsigned long)arg2; \
2252 _argvec[2+3] = (unsigned long)arg3; \
2253 _argvec[2+4] = (unsigned long)arg4; \
2254 _argvec[2+5] = (unsigned long)arg5; \
2255 _argvec[2+6] = (unsigned long)arg6; \
2256 _argvec[2+7] = (unsigned long)arg7; \
2257 __asm__ volatile( \
2258 "mr 11,%1\n\t" \
2259 "std 2,-16(11)\n\t" /* save tocptr */ \
2260 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2261 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2262 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2263 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2264 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2265 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2266 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2267 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2268 "ld 11, 0(11)\n\t" /* target->r11 */ \
2269 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2270 "mr 11,%1\n\t" \
2271 "mr %0,3\n\t" \
2272 "ld 2,-16(11)" /* restore tocptr */ \
2273 : /*out*/ "=r" (_res) \
2274 : /*in*/ "r" (&_argvec[2]) \
2275 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2276 ); \
2277 lval = (__typeof__(lval)) _res; \
2278 } while (0)
2279
2280#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2281 arg7,arg8) \
2282 do { \
2283 volatile OrigFn _orig = (orig); \
2284 volatile unsigned long _argvec[3+8]; \
2285 volatile unsigned long _res; \
2286 /* _argvec[0] holds current r2 across the call */ \
2287 _argvec[1] = (unsigned long)_orig.r2; \
2288 _argvec[2] = (unsigned long)_orig.nraddr; \
2289 _argvec[2+1] = (unsigned long)arg1; \
2290 _argvec[2+2] = (unsigned long)arg2; \
2291 _argvec[2+3] = (unsigned long)arg3; \
2292 _argvec[2+4] = (unsigned long)arg4; \
2293 _argvec[2+5] = (unsigned long)arg5; \
2294 _argvec[2+6] = (unsigned long)arg6; \
2295 _argvec[2+7] = (unsigned long)arg7; \
2296 _argvec[2+8] = (unsigned long)arg8; \
2297 __asm__ volatile( \
2298 "mr 11,%1\n\t" \
2299 "std 2,-16(11)\n\t" /* save tocptr */ \
2300 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2301 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2302 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2303 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2304 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2305 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2306 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2307 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2308 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2309 "ld 11, 0(11)\n\t" /* target->r11 */ \
2310 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2311 "mr 11,%1\n\t" \
2312 "mr %0,3\n\t" \
2313 "ld 2,-16(11)" /* restore tocptr */ \
2314 : /*out*/ "=r" (_res) \
2315 : /*in*/ "r" (&_argvec[2]) \
2316 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2317 ); \
2318 lval = (__typeof__(lval)) _res; \
2319 } while (0)
2320
2321#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2322 arg7,arg8,arg9) \
2323 do { \
2324 volatile OrigFn _orig = (orig); \
2325 volatile unsigned long _argvec[3+9]; \
2326 volatile unsigned long _res; \
2327 /* _argvec[0] holds current r2 across the call */ \
2328 _argvec[1] = (unsigned long)_orig.r2; \
2329 _argvec[2] = (unsigned long)_orig.nraddr; \
2330 _argvec[2+1] = (unsigned long)arg1; \
2331 _argvec[2+2] = (unsigned long)arg2; \
2332 _argvec[2+3] = (unsigned long)arg3; \
2333 _argvec[2+4] = (unsigned long)arg4; \
2334 _argvec[2+5] = (unsigned long)arg5; \
2335 _argvec[2+6] = (unsigned long)arg6; \
2336 _argvec[2+7] = (unsigned long)arg7; \
2337 _argvec[2+8] = (unsigned long)arg8; \
2338 _argvec[2+9] = (unsigned long)arg9; \
2339 __asm__ volatile( \
2340 "mr 11,%1\n\t" \
2341 "std 2,-16(11)\n\t" /* save tocptr */ \
2342 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2343 "addi 1,1,-128\n\t" /* expand stack frame */ \
2344 /* arg9 */ \
2345 "ld 3,72(11)\n\t" \
2346 "std 3,112(1)\n\t" \
2347 /* args1-8 */ \
2348 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2349 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2350 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2351 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2352 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2353 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2354 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2355 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2356 "ld 11, 0(11)\n\t" /* target->r11 */ \
2357 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2358 "mr 11,%1\n\t" \
2359 "mr %0,3\n\t" \
2360 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2361 "addi 1,1,128" /* restore frame */ \
2362 : /*out*/ "=r" (_res) \
2363 : /*in*/ "r" (&_argvec[2]) \
2364 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2365 ); \
2366 lval = (__typeof__(lval)) _res; \
2367 } while (0)
2368
2369#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2370 arg7,arg8,arg9,arg10) \
2371 do { \
2372 volatile OrigFn _orig = (orig); \
2373 volatile unsigned long _argvec[3+10]; \
2374 volatile unsigned long _res; \
2375 /* _argvec[0] holds current r2 across the call */ \
2376 _argvec[1] = (unsigned long)_orig.r2; \
2377 _argvec[2] = (unsigned long)_orig.nraddr; \
2378 _argvec[2+1] = (unsigned long)arg1; \
2379 _argvec[2+2] = (unsigned long)arg2; \
2380 _argvec[2+3] = (unsigned long)arg3; \
2381 _argvec[2+4] = (unsigned long)arg4; \
2382 _argvec[2+5] = (unsigned long)arg5; \
2383 _argvec[2+6] = (unsigned long)arg6; \
2384 _argvec[2+7] = (unsigned long)arg7; \
2385 _argvec[2+8] = (unsigned long)arg8; \
2386 _argvec[2+9] = (unsigned long)arg9; \
2387 _argvec[2+10] = (unsigned long)arg10; \
2388 __asm__ volatile( \
2389 "mr 11,%1\n\t" \
2390 "std 2,-16(11)\n\t" /* save tocptr */ \
2391 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2392 "addi 1,1,-128\n\t" /* expand stack frame */ \
2393 /* arg10 */ \
2394 "ld 3,80(11)\n\t" \
2395 "std 3,120(1)\n\t" \
2396 /* arg9 */ \
2397 "ld 3,72(11)\n\t" \
2398 "std 3,112(1)\n\t" \
2399 /* args1-8 */ \
2400 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2401 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2402 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2403 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2404 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2405 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2406 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2407 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2408 "ld 11, 0(11)\n\t" /* target->r11 */ \
2409 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2410 "mr 11,%1\n\t" \
2411 "mr %0,3\n\t" \
2412 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2413 "addi 1,1,128" /* restore frame */ \
2414 : /*out*/ "=r" (_res) \
2415 : /*in*/ "r" (&_argvec[2]) \
2416 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2417 ); \
2418 lval = (__typeof__(lval)) _res; \
2419 } while (0)
2420
2421#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2422 arg7,arg8,arg9,arg10,arg11) \
2423 do { \
2424 volatile OrigFn _orig = (orig); \
2425 volatile unsigned long _argvec[3+11]; \
2426 volatile unsigned long _res; \
2427 /* _argvec[0] holds current r2 across the call */ \
2428 _argvec[1] = (unsigned long)_orig.r2; \
2429 _argvec[2] = (unsigned long)_orig.nraddr; \
2430 _argvec[2+1] = (unsigned long)arg1; \
2431 _argvec[2+2] = (unsigned long)arg2; \
2432 _argvec[2+3] = (unsigned long)arg3; \
2433 _argvec[2+4] = (unsigned long)arg4; \
2434 _argvec[2+5] = (unsigned long)arg5; \
2435 _argvec[2+6] = (unsigned long)arg6; \
2436 _argvec[2+7] = (unsigned long)arg7; \
2437 _argvec[2+8] = (unsigned long)arg8; \
2438 _argvec[2+9] = (unsigned long)arg9; \
2439 _argvec[2+10] = (unsigned long)arg10; \
2440 _argvec[2+11] = (unsigned long)arg11; \
2441 __asm__ volatile( \
2442 "mr 11,%1\n\t" \
2443 "std 2,-16(11)\n\t" /* save tocptr */ \
2444 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2445 "addi 1,1,-144\n\t" /* expand stack frame */ \
2446 /* arg11 */ \
2447 "ld 3,88(11)\n\t" \
2448 "std 3,128(1)\n\t" \
2449 /* arg10 */ \
2450 "ld 3,80(11)\n\t" \
2451 "std 3,120(1)\n\t" \
2452 /* arg9 */ \
2453 "ld 3,72(11)\n\t" \
2454 "std 3,112(1)\n\t" \
2455 /* args1-8 */ \
2456 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2457 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2458 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2459 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2460 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2461 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2462 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2463 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2464 "ld 11, 0(11)\n\t" /* target->r11 */ \
2465 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2466 "mr 11,%1\n\t" \
2467 "mr %0,3\n\t" \
2468 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2469 "addi 1,1,144" /* restore frame */ \
2470 : /*out*/ "=r" (_res) \
2471 : /*in*/ "r" (&_argvec[2]) \
2472 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2473 ); \
2474 lval = (__typeof__(lval)) _res; \
2475 } while (0)
2476
2477#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2478 arg7,arg8,arg9,arg10,arg11,arg12) \
2479 do { \
2480 volatile OrigFn _orig = (orig); \
2481 volatile unsigned long _argvec[3+12]; \
2482 volatile unsigned long _res; \
2483 /* _argvec[0] holds current r2 across the call */ \
2484 _argvec[1] = (unsigned long)_orig.r2; \
2485 _argvec[2] = (unsigned long)_orig.nraddr; \
2486 _argvec[2+1] = (unsigned long)arg1; \
2487 _argvec[2+2] = (unsigned long)arg2; \
2488 _argvec[2+3] = (unsigned long)arg3; \
2489 _argvec[2+4] = (unsigned long)arg4; \
2490 _argvec[2+5] = (unsigned long)arg5; \
2491 _argvec[2+6] = (unsigned long)arg6; \
2492 _argvec[2+7] = (unsigned long)arg7; \
2493 _argvec[2+8] = (unsigned long)arg8; \
2494 _argvec[2+9] = (unsigned long)arg9; \
2495 _argvec[2+10] = (unsigned long)arg10; \
2496 _argvec[2+11] = (unsigned long)arg11; \
2497 _argvec[2+12] = (unsigned long)arg12; \
2498 __asm__ volatile( \
2499 "mr 11,%1\n\t" \
2500 "std 2,-16(11)\n\t" /* save tocptr */ \
2501 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
2502 "addi 1,1,-144\n\t" /* expand stack frame */ \
2503 /* arg12 */ \
2504 "ld 3,96(11)\n\t" \
2505 "std 3,136(1)\n\t" \
2506 /* arg11 */ \
2507 "ld 3,88(11)\n\t" \
2508 "std 3,128(1)\n\t" \
2509 /* arg10 */ \
2510 "ld 3,80(11)\n\t" \
2511 "std 3,120(1)\n\t" \
2512 /* arg9 */ \
2513 "ld 3,72(11)\n\t" \
2514 "std 3,112(1)\n\t" \
2515 /* args1-8 */ \
2516 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
2517 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
2518 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
2519 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
2520 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
2521 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
2522 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
2523 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
2524 "ld 11, 0(11)\n\t" /* target->r11 */ \
2525 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2526 "mr 11,%1\n\t" \
2527 "mr %0,3\n\t" \
2528 "ld 2,-16(11)\n\t" /* restore tocptr */ \
2529 "addi 1,1,144" /* restore frame */ \
2530 : /*out*/ "=r" (_res) \
2531 : /*in*/ "r" (&_argvec[2]) \
2532 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2533 ); \
2534 lval = (__typeof__(lval)) _res; \
2535 } while (0)
2536
sewardjf5c1a7f2006-10-17 01:32:48 +00002537#endif /* PLAT_ppc64_linux */
2538
sewardj59570ff2010-01-01 11:59:33 +00002539/* ------------------------- arm-linux ------------------------- */
2540
2541#if defined(PLAT_arm_linux)
2542
2543/* These regs are trashed by the hidden call. */
2544#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
2545
2546/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
2547 long) == 4. */
2548
2549#define CALL_FN_W_v(lval, orig) \
2550 do { \
2551 volatile OrigFn _orig = (orig); \
2552 volatile unsigned long _argvec[1]; \
2553 volatile unsigned long _res; \
2554 _argvec[0] = (unsigned long)_orig.nraddr; \
2555 __asm__ volatile( \
2556 "ldr r4, [%1] \n\t" /* target->r4 */ \
2557 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2558 "mov %0, r0\n" \
2559 : /*out*/ "=r" (_res) \
2560 : /*in*/ "0" (&_argvec[0]) \
2561 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2562 ); \
2563 lval = (__typeof__(lval)) _res; \
2564 } while (0)
2565
2566#define CALL_FN_W_W(lval, orig, arg1) \
2567 do { \
2568 volatile OrigFn _orig = (orig); \
2569 volatile unsigned long _argvec[2]; \
2570 volatile unsigned long _res; \
2571 _argvec[0] = (unsigned long)_orig.nraddr; \
2572 _argvec[1] = (unsigned long)(arg1); \
2573 __asm__ volatile( \
2574 "ldr r0, [%1, #4] \n\t" \
2575 "ldr r4, [%1] \n\t" /* target->r4 */ \
2576 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2577 "mov %0, r0\n" \
2578 : /*out*/ "=r" (_res) \
2579 : /*in*/ "0" (&_argvec[0]) \
2580 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2581 ); \
2582 lval = (__typeof__(lval)) _res; \
2583 } while (0)
2584
2585#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
2586 do { \
2587 volatile OrigFn _orig = (orig); \
2588 volatile unsigned long _argvec[3]; \
2589 volatile unsigned long _res; \
2590 _argvec[0] = (unsigned long)_orig.nraddr; \
2591 _argvec[1] = (unsigned long)(arg1); \
2592 _argvec[2] = (unsigned long)(arg2); \
2593 __asm__ volatile( \
2594 "ldr r0, [%1, #4] \n\t" \
2595 "ldr r1, [%1, #8] \n\t" \
2596 "ldr r4, [%1] \n\t" /* target->r4 */ \
2597 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2598 "mov %0, r0\n" \
2599 : /*out*/ "=r" (_res) \
2600 : /*in*/ "0" (&_argvec[0]) \
2601 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2602 ); \
2603 lval = (__typeof__(lval)) _res; \
2604 } while (0)
2605
2606#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
2607 do { \
2608 volatile OrigFn _orig = (orig); \
2609 volatile unsigned long _argvec[4]; \
2610 volatile unsigned long _res; \
2611 _argvec[0] = (unsigned long)_orig.nraddr; \
2612 _argvec[1] = (unsigned long)(arg1); \
2613 _argvec[2] = (unsigned long)(arg2); \
2614 _argvec[3] = (unsigned long)(arg3); \
2615 __asm__ volatile( \
2616 "ldr r0, [%1, #4] \n\t" \
2617 "ldr r1, [%1, #8] \n\t" \
2618 "ldr r2, [%1, #12] \n\t" \
2619 "ldr r4, [%1] \n\t" /* target->r4 */ \
2620 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2621 "mov %0, r0\n" \
2622 : /*out*/ "=r" (_res) \
2623 : /*in*/ "0" (&_argvec[0]) \
2624 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2625 ); \
2626 lval = (__typeof__(lval)) _res; \
2627 } while (0)
2628
2629#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
2630 do { \
2631 volatile OrigFn _orig = (orig); \
2632 volatile unsigned long _argvec[5]; \
2633 volatile unsigned long _res; \
2634 _argvec[0] = (unsigned long)_orig.nraddr; \
2635 _argvec[1] = (unsigned long)(arg1); \
2636 _argvec[2] = (unsigned long)(arg2); \
2637 _argvec[3] = (unsigned long)(arg3); \
2638 _argvec[4] = (unsigned long)(arg4); \
2639 __asm__ volatile( \
2640 "ldr r0, [%1, #4] \n\t" \
2641 "ldr r1, [%1, #8] \n\t" \
2642 "ldr r2, [%1, #12] \n\t" \
2643 "ldr r3, [%1, #16] \n\t" \
2644 "ldr r4, [%1] \n\t" /* target->r4 */ \
2645 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2646 "mov %0, r0" \
2647 : /*out*/ "=r" (_res) \
2648 : /*in*/ "0" (&_argvec[0]) \
2649 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2650 ); \
2651 lval = (__typeof__(lval)) _res; \
2652 } while (0)
2653
2654#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
2655 do { \
2656 volatile OrigFn _orig = (orig); \
2657 volatile unsigned long _argvec[6]; \
2658 volatile unsigned long _res; \
2659 _argvec[0] = (unsigned long)_orig.nraddr; \
2660 _argvec[1] = (unsigned long)(arg1); \
2661 _argvec[2] = (unsigned long)(arg2); \
2662 _argvec[3] = (unsigned long)(arg3); \
2663 _argvec[4] = (unsigned long)(arg4); \
2664 _argvec[5] = (unsigned long)(arg5); \
2665 __asm__ volatile( \
2666 "ldr r0, [%1, #20] \n\t" \
2667 "push {r0} \n\t" \
2668 "ldr r0, [%1, #4] \n\t" \
2669 "ldr r1, [%1, #8] \n\t" \
2670 "ldr r2, [%1, #12] \n\t" \
2671 "ldr r3, [%1, #16] \n\t" \
2672 "ldr r4, [%1] \n\t" /* target->r4 */ \
2673 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2674 "add sp, sp, #4 \n\t" \
2675 "mov %0, r0" \
2676 : /*out*/ "=r" (_res) \
2677 : /*in*/ "0" (&_argvec[0]) \
2678 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2679 ); \
2680 lval = (__typeof__(lval)) _res; \
2681 } while (0)
2682
2683#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
2684 do { \
2685 volatile OrigFn _orig = (orig); \
2686 volatile unsigned long _argvec[7]; \
2687 volatile unsigned long _res; \
2688 _argvec[0] = (unsigned long)_orig.nraddr; \
2689 _argvec[1] = (unsigned long)(arg1); \
2690 _argvec[2] = (unsigned long)(arg2); \
2691 _argvec[3] = (unsigned long)(arg3); \
2692 _argvec[4] = (unsigned long)(arg4); \
2693 _argvec[5] = (unsigned long)(arg5); \
2694 _argvec[6] = (unsigned long)(arg6); \
2695 __asm__ volatile( \
2696 "ldr r0, [%1, #20] \n\t" \
2697 "ldr r1, [%1, #24] \n\t" \
2698 "push {r0, r1} \n\t" \
2699 "ldr r0, [%1, #4] \n\t" \
2700 "ldr r1, [%1, #8] \n\t" \
2701 "ldr r2, [%1, #12] \n\t" \
2702 "ldr r3, [%1, #16] \n\t" \
2703 "ldr r4, [%1] \n\t" /* target->r4 */ \
2704 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2705 "add sp, sp, #8 \n\t" \
2706 "mov %0, r0" \
2707 : /*out*/ "=r" (_res) \
2708 : /*in*/ "0" (&_argvec[0]) \
2709 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2710 ); \
2711 lval = (__typeof__(lval)) _res; \
2712 } while (0)
2713
2714#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2715 arg7) \
2716 do { \
2717 volatile OrigFn _orig = (orig); \
2718 volatile unsigned long _argvec[8]; \
2719 volatile unsigned long _res; \
2720 _argvec[0] = (unsigned long)_orig.nraddr; \
2721 _argvec[1] = (unsigned long)(arg1); \
2722 _argvec[2] = (unsigned long)(arg2); \
2723 _argvec[3] = (unsigned long)(arg3); \
2724 _argvec[4] = (unsigned long)(arg4); \
2725 _argvec[5] = (unsigned long)(arg5); \
2726 _argvec[6] = (unsigned long)(arg6); \
2727 _argvec[7] = (unsigned long)(arg7); \
2728 __asm__ volatile( \
2729 "ldr r0, [%1, #20] \n\t" \
2730 "ldr r1, [%1, #24] \n\t" \
2731 "ldr r2, [%1, #28] \n\t" \
2732 "push {r0, r1, r2} \n\t" \
2733 "ldr r0, [%1, #4] \n\t" \
2734 "ldr r1, [%1, #8] \n\t" \
2735 "ldr r2, [%1, #12] \n\t" \
2736 "ldr r3, [%1, #16] \n\t" \
2737 "ldr r4, [%1] \n\t" /* target->r4 */ \
2738 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2739 "add sp, sp, #12 \n\t" \
2740 "mov %0, r0" \
2741 : /*out*/ "=r" (_res) \
2742 : /*in*/ "0" (&_argvec[0]) \
2743 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2744 ); \
2745 lval = (__typeof__(lval)) _res; \
2746 } while (0)
2747
2748#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2749 arg7,arg8) \
2750 do { \
2751 volatile OrigFn _orig = (orig); \
2752 volatile unsigned long _argvec[9]; \
2753 volatile unsigned long _res; \
2754 _argvec[0] = (unsigned long)_orig.nraddr; \
2755 _argvec[1] = (unsigned long)(arg1); \
2756 _argvec[2] = (unsigned long)(arg2); \
2757 _argvec[3] = (unsigned long)(arg3); \
2758 _argvec[4] = (unsigned long)(arg4); \
2759 _argvec[5] = (unsigned long)(arg5); \
2760 _argvec[6] = (unsigned long)(arg6); \
2761 _argvec[7] = (unsigned long)(arg7); \
2762 _argvec[8] = (unsigned long)(arg8); \
2763 __asm__ volatile( \
2764 "ldr r0, [%1, #20] \n\t" \
2765 "ldr r1, [%1, #24] \n\t" \
2766 "ldr r2, [%1, #28] \n\t" \
2767 "ldr r3, [%1, #32] \n\t" \
2768 "push {r0, r1, r2, r3} \n\t" \
2769 "ldr r0, [%1, #4] \n\t" \
2770 "ldr r1, [%1, #8] \n\t" \
2771 "ldr r2, [%1, #12] \n\t" \
2772 "ldr r3, [%1, #16] \n\t" \
2773 "ldr r4, [%1] \n\t" /* target->r4 */ \
2774 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2775 "add sp, sp, #16 \n\t" \
2776 "mov %0, r0" \
2777 : /*out*/ "=r" (_res) \
2778 : /*in*/ "0" (&_argvec[0]) \
2779 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2780 ); \
2781 lval = (__typeof__(lval)) _res; \
2782 } while (0)
2783
2784#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2785 arg7,arg8,arg9) \
2786 do { \
2787 volatile OrigFn _orig = (orig); \
2788 volatile unsigned long _argvec[10]; \
2789 volatile unsigned long _res; \
2790 _argvec[0] = (unsigned long)_orig.nraddr; \
2791 _argvec[1] = (unsigned long)(arg1); \
2792 _argvec[2] = (unsigned long)(arg2); \
2793 _argvec[3] = (unsigned long)(arg3); \
2794 _argvec[4] = (unsigned long)(arg4); \
2795 _argvec[5] = (unsigned long)(arg5); \
2796 _argvec[6] = (unsigned long)(arg6); \
2797 _argvec[7] = (unsigned long)(arg7); \
2798 _argvec[8] = (unsigned long)(arg8); \
2799 _argvec[9] = (unsigned long)(arg9); \
2800 __asm__ volatile( \
2801 "ldr r0, [%1, #20] \n\t" \
2802 "ldr r1, [%1, #24] \n\t" \
2803 "ldr r2, [%1, #28] \n\t" \
2804 "ldr r3, [%1, #32] \n\t" \
2805 "ldr r4, [%1, #36] \n\t" \
2806 "push {r0, r1, r2, r3, r4} \n\t" \
2807 "ldr r0, [%1, #4] \n\t" \
2808 "ldr r1, [%1, #8] \n\t" \
2809 "ldr r2, [%1, #12] \n\t" \
2810 "ldr r3, [%1, #16] \n\t" \
2811 "ldr r4, [%1] \n\t" /* target->r4 */ \
2812 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2813 "add sp, sp, #20 \n\t" \
2814 "mov %0, r0" \
2815 : /*out*/ "=r" (_res) \
2816 : /*in*/ "0" (&_argvec[0]) \
2817 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2818 ); \
2819 lval = (__typeof__(lval)) _res; \
2820 } while (0)
2821
2822#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
2823 arg7,arg8,arg9,arg10) \
2824 do { \
2825 volatile OrigFn _orig = (orig); \
2826 volatile unsigned long _argvec[11]; \
2827 volatile unsigned long _res; \
2828 _argvec[0] = (unsigned long)_orig.nraddr; \
2829 _argvec[1] = (unsigned long)(arg1); \
2830 _argvec[2] = (unsigned long)(arg2); \
2831 _argvec[3] = (unsigned long)(arg3); \
2832 _argvec[4] = (unsigned long)(arg4); \
2833 _argvec[5] = (unsigned long)(arg5); \
2834 _argvec[6] = (unsigned long)(arg6); \
2835 _argvec[7] = (unsigned long)(arg7); \
2836 _argvec[8] = (unsigned long)(arg8); \
2837 _argvec[9] = (unsigned long)(arg9); \
2838 _argvec[10] = (unsigned long)(arg10); \
2839 __asm__ volatile( \
2840 "ldr r0, [%1, #40] \n\t" \
2841 "push {r0} \n\t" \
2842 "ldr r0, [%1, #20] \n\t" \
2843 "ldr r1, [%1, #24] \n\t" \
2844 "ldr r2, [%1, #28] \n\t" \
2845 "ldr r3, [%1, #32] \n\t" \
2846 "ldr r4, [%1, #36] \n\t" \
2847 "push {r0, r1, r2, r3, r4} \n\t" \
2848 "ldr r0, [%1, #4] \n\t" \
2849 "ldr r1, [%1, #8] \n\t" \
2850 "ldr r2, [%1, #12] \n\t" \
2851 "ldr r3, [%1, #16] \n\t" \
2852 "ldr r4, [%1] \n\t" /* target->r4 */ \
2853 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2854 "add sp, sp, #24 \n\t" \
2855 "mov %0, r0" \
2856 : /*out*/ "=r" (_res) \
2857 : /*in*/ "0" (&_argvec[0]) \
2858 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2859 ); \
2860 lval = (__typeof__(lval)) _res; \
2861 } while (0)
2862
2863#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
2864 arg6,arg7,arg8,arg9,arg10, \
2865 arg11) \
2866 do { \
2867 volatile OrigFn _orig = (orig); \
2868 volatile unsigned long _argvec[12]; \
2869 volatile unsigned long _res; \
2870 _argvec[0] = (unsigned long)_orig.nraddr; \
2871 _argvec[1] = (unsigned long)(arg1); \
2872 _argvec[2] = (unsigned long)(arg2); \
2873 _argvec[3] = (unsigned long)(arg3); \
2874 _argvec[4] = (unsigned long)(arg4); \
2875 _argvec[5] = (unsigned long)(arg5); \
2876 _argvec[6] = (unsigned long)(arg6); \
2877 _argvec[7] = (unsigned long)(arg7); \
2878 _argvec[8] = (unsigned long)(arg8); \
2879 _argvec[9] = (unsigned long)(arg9); \
2880 _argvec[10] = (unsigned long)(arg10); \
2881 _argvec[11] = (unsigned long)(arg11); \
2882 __asm__ volatile( \
2883 "ldr r0, [%1, #40] \n\t" \
2884 "ldr r1, [%1, #44] \n\t" \
2885 "push {r0, r1} \n\t" \
2886 "ldr r0, [%1, #20] \n\t" \
2887 "ldr r1, [%1, #24] \n\t" \
2888 "ldr r2, [%1, #28] \n\t" \
2889 "ldr r3, [%1, #32] \n\t" \
2890 "ldr r4, [%1, #36] \n\t" \
2891 "push {r0, r1, r2, r3, r4} \n\t" \
2892 "ldr r0, [%1, #4] \n\t" \
2893 "ldr r1, [%1, #8] \n\t" \
2894 "ldr r2, [%1, #12] \n\t" \
2895 "ldr r3, [%1, #16] \n\t" \
2896 "ldr r4, [%1] \n\t" /* target->r4 */ \
2897 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2898 "add sp, sp, #28 \n\t" \
2899 "mov %0, r0" \
2900 : /*out*/ "=r" (_res) \
2901 : /*in*/ "0" (&_argvec[0]) \
2902 : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \
2903 ); \
2904 lval = (__typeof__(lval)) _res; \
2905 } while (0)
2906
2907#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
2908 arg6,arg7,arg8,arg9,arg10, \
2909 arg11,arg12) \
2910 do { \
2911 volatile OrigFn _orig = (orig); \
2912 volatile unsigned long _argvec[13]; \
2913 volatile unsigned long _res; \
2914 _argvec[0] = (unsigned long)_orig.nraddr; \
2915 _argvec[1] = (unsigned long)(arg1); \
2916 _argvec[2] = (unsigned long)(arg2); \
2917 _argvec[3] = (unsigned long)(arg3); \
2918 _argvec[4] = (unsigned long)(arg4); \
2919 _argvec[5] = (unsigned long)(arg5); \
2920 _argvec[6] = (unsigned long)(arg6); \
2921 _argvec[7] = (unsigned long)(arg7); \
2922 _argvec[8] = (unsigned long)(arg8); \
2923 _argvec[9] = (unsigned long)(arg9); \
2924 _argvec[10] = (unsigned long)(arg10); \
2925 _argvec[11] = (unsigned long)(arg11); \
2926 _argvec[12] = (unsigned long)(arg12); \
2927 __asm__ volatile( \
2928 "ldr r0, [%1, #40] \n\t" \
2929 "ldr r1, [%1, #44] \n\t" \
2930 "ldr r2, [%1, #48] \n\t" \
2931 "push {r0, r1, r2} \n\t" \
2932 "ldr r0, [%1, #20] \n\t" \
2933 "ldr r1, [%1, #24] \n\t" \
2934 "ldr r2, [%1, #28] \n\t" \
2935 "ldr r3, [%1, #32] \n\t" \
2936 "ldr r4, [%1, #36] \n\t" \
2937 "push {r0, r1, r2, r3, r4} \n\t" \
2938 "ldr r0, [%1, #4] \n\t" \
2939 "ldr r1, [%1, #8] \n\t" \
2940 "ldr r2, [%1, #12] \n\t" \
2941 "ldr r3, [%1, #16] \n\t" \
2942 "ldr r4, [%1] \n\t" /* target->r4 */ \
2943 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
2944 "add sp, sp, #32 \n\t" \
2945 "mov %0, r0" \
2946 : /*out*/ "=r" (_res) \
2947 : /*in*/ "0" (&_argvec[0]) \
2948 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
2949 ); \
2950 lval = (__typeof__(lval)) _res; \
2951 } while (0)
2952
2953#endif /* PLAT_arm_linux */
2954
sewardjf5c1a7f2006-10-17 01:32:48 +00002955/* ------------------------ ppc32-aix5 ------------------------- */
2956
2957#if defined(PLAT_ppc32_aix5)
2958
2959/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2960
2961/* These regs are trashed by the hidden call. */
2962#define __CALLER_SAVED_REGS \
2963 "lr", "ctr", "xer", \
2964 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
2965 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
2966 "r11", "r12", "r13"
2967
2968/* Expand the stack frame, copying enough info that unwinding
2969 still works. Trashes r3. */
2970
2971#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
2972 "addi 1,1,-" #_n_fr "\n\t" \
2973 "lwz 3," #_n_fr "(1)\n\t" \
2974 "stw 3,0(1)\n\t"
2975
2976#define VG_CONTRACT_FRAME_BY(_n_fr) \
2977 "addi 1,1," #_n_fr "\n\t"
2978
2979/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
2980 long) == 4. */
2981
2982#define CALL_FN_W_v(lval, orig) \
2983 do { \
2984 volatile OrigFn _orig = (orig); \
2985 volatile unsigned long _argvec[3+0]; \
2986 volatile unsigned long _res; \
2987 /* _argvec[0] holds current r2 across the call */ \
2988 _argvec[1] = (unsigned long)_orig.r2; \
2989 _argvec[2] = (unsigned long)_orig.nraddr; \
2990 __asm__ volatile( \
2991 "mr 11,%1\n\t" \
2992 VG_EXPAND_FRAME_BY_trashes_r3(512) \
2993 "stw 2,-8(11)\n\t" /* save tocptr */ \
2994 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
2995 "lwz 11, 0(11)\n\t" /* target->r11 */ \
2996 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
2997 "mr 11,%1\n\t" \
2998 "mr %0,3\n\t" \
2999 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3000 VG_CONTRACT_FRAME_BY(512) \
3001 : /*out*/ "=r" (_res) \
3002 : /*in*/ "r" (&_argvec[2]) \
3003 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3004 ); \
3005 lval = (__typeof__(lval)) _res; \
3006 } while (0)
3007
3008#define CALL_FN_W_W(lval, orig, arg1) \
3009 do { \
3010 volatile OrigFn _orig = (orig); \
3011 volatile unsigned long _argvec[3+1]; \
3012 volatile unsigned long _res; \
3013 /* _argvec[0] holds current r2 across the call */ \
3014 _argvec[1] = (unsigned long)_orig.r2; \
3015 _argvec[2] = (unsigned long)_orig.nraddr; \
3016 _argvec[2+1] = (unsigned long)arg1; \
3017 __asm__ volatile( \
3018 "mr 11,%1\n\t" \
3019 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3020 "stw 2,-8(11)\n\t" /* save tocptr */ \
3021 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3022 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3023 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3024 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3025 "mr 11,%1\n\t" \
3026 "mr %0,3\n\t" \
3027 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3028 VG_CONTRACT_FRAME_BY(512) \
3029 : /*out*/ "=r" (_res) \
3030 : /*in*/ "r" (&_argvec[2]) \
3031 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3032 ); \
3033 lval = (__typeof__(lval)) _res; \
3034 } while (0)
3035
3036#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3037 do { \
3038 volatile OrigFn _orig = (orig); \
3039 volatile unsigned long _argvec[3+2]; \
3040 volatile unsigned long _res; \
3041 /* _argvec[0] holds current r2 across the call */ \
3042 _argvec[1] = (unsigned long)_orig.r2; \
3043 _argvec[2] = (unsigned long)_orig.nraddr; \
3044 _argvec[2+1] = (unsigned long)arg1; \
3045 _argvec[2+2] = (unsigned long)arg2; \
3046 __asm__ volatile( \
3047 "mr 11,%1\n\t" \
3048 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3049 "stw 2,-8(11)\n\t" /* save tocptr */ \
3050 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3051 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3052 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3053 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3054 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3055 "mr 11,%1\n\t" \
3056 "mr %0,3\n\t" \
3057 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3058 VG_CONTRACT_FRAME_BY(512) \
3059 : /*out*/ "=r" (_res) \
3060 : /*in*/ "r" (&_argvec[2]) \
3061 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3062 ); \
3063 lval = (__typeof__(lval)) _res; \
3064 } while (0)
3065
3066#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3067 do { \
3068 volatile OrigFn _orig = (orig); \
3069 volatile unsigned long _argvec[3+3]; \
3070 volatile unsigned long _res; \
3071 /* _argvec[0] holds current r2 across the call */ \
3072 _argvec[1] = (unsigned long)_orig.r2; \
3073 _argvec[2] = (unsigned long)_orig.nraddr; \
3074 _argvec[2+1] = (unsigned long)arg1; \
3075 _argvec[2+2] = (unsigned long)arg2; \
3076 _argvec[2+3] = (unsigned long)arg3; \
3077 __asm__ volatile( \
3078 "mr 11,%1\n\t" \
3079 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3080 "stw 2,-8(11)\n\t" /* save tocptr */ \
3081 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3082 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3083 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3084 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3085 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3086 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3087 "mr 11,%1\n\t" \
3088 "mr %0,3\n\t" \
3089 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3090 VG_CONTRACT_FRAME_BY(512) \
3091 : /*out*/ "=r" (_res) \
3092 : /*in*/ "r" (&_argvec[2]) \
3093 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3094 ); \
3095 lval = (__typeof__(lval)) _res; \
3096 } while (0)
3097
3098#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3099 do { \
3100 volatile OrigFn _orig = (orig); \
3101 volatile unsigned long _argvec[3+4]; \
3102 volatile unsigned long _res; \
3103 /* _argvec[0] holds current r2 across the call */ \
3104 _argvec[1] = (unsigned long)_orig.r2; \
3105 _argvec[2] = (unsigned long)_orig.nraddr; \
3106 _argvec[2+1] = (unsigned long)arg1; \
3107 _argvec[2+2] = (unsigned long)arg2; \
3108 _argvec[2+3] = (unsigned long)arg3; \
3109 _argvec[2+4] = (unsigned long)arg4; \
3110 __asm__ volatile( \
3111 "mr 11,%1\n\t" \
3112 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3113 "stw 2,-8(11)\n\t" /* save tocptr */ \
3114 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3115 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3116 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3117 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3118 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3119 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3120 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3121 "mr 11,%1\n\t" \
3122 "mr %0,3\n\t" \
3123 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3124 VG_CONTRACT_FRAME_BY(512) \
3125 : /*out*/ "=r" (_res) \
3126 : /*in*/ "r" (&_argvec[2]) \
3127 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3128 ); \
3129 lval = (__typeof__(lval)) _res; \
3130 } while (0)
3131
3132#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3133 do { \
3134 volatile OrigFn _orig = (orig); \
3135 volatile unsigned long _argvec[3+5]; \
3136 volatile unsigned long _res; \
3137 /* _argvec[0] holds current r2 across the call */ \
3138 _argvec[1] = (unsigned long)_orig.r2; \
3139 _argvec[2] = (unsigned long)_orig.nraddr; \
3140 _argvec[2+1] = (unsigned long)arg1; \
3141 _argvec[2+2] = (unsigned long)arg2; \
3142 _argvec[2+3] = (unsigned long)arg3; \
3143 _argvec[2+4] = (unsigned long)arg4; \
3144 _argvec[2+5] = (unsigned long)arg5; \
3145 __asm__ volatile( \
3146 "mr 11,%1\n\t" \
3147 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3148 "stw 2,-8(11)\n\t" /* save tocptr */ \
3149 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3150 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3151 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3152 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3153 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3154 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3155 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3156 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3157 "mr 11,%1\n\t" \
3158 "mr %0,3\n\t" \
3159 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3160 VG_CONTRACT_FRAME_BY(512) \
3161 : /*out*/ "=r" (_res) \
3162 : /*in*/ "r" (&_argvec[2]) \
3163 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3164 ); \
3165 lval = (__typeof__(lval)) _res; \
3166 } while (0)
3167
3168#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3169 do { \
3170 volatile OrigFn _orig = (orig); \
3171 volatile unsigned long _argvec[3+6]; \
3172 volatile unsigned long _res; \
3173 /* _argvec[0] holds current r2 across the call */ \
3174 _argvec[1] = (unsigned long)_orig.r2; \
3175 _argvec[2] = (unsigned long)_orig.nraddr; \
3176 _argvec[2+1] = (unsigned long)arg1; \
3177 _argvec[2+2] = (unsigned long)arg2; \
3178 _argvec[2+3] = (unsigned long)arg3; \
3179 _argvec[2+4] = (unsigned long)arg4; \
3180 _argvec[2+5] = (unsigned long)arg5; \
3181 _argvec[2+6] = (unsigned long)arg6; \
3182 __asm__ volatile( \
3183 "mr 11,%1\n\t" \
3184 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3185 "stw 2,-8(11)\n\t" /* save tocptr */ \
3186 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3187 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3188 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3189 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3190 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3191 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3192 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3193 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3194 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3195 "mr 11,%1\n\t" \
3196 "mr %0,3\n\t" \
3197 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3198 VG_CONTRACT_FRAME_BY(512) \
3199 : /*out*/ "=r" (_res) \
3200 : /*in*/ "r" (&_argvec[2]) \
3201 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3202 ); \
3203 lval = (__typeof__(lval)) _res; \
3204 } while (0)
3205
3206#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3207 arg7) \
3208 do { \
3209 volatile OrigFn _orig = (orig); \
3210 volatile unsigned long _argvec[3+7]; \
3211 volatile unsigned long _res; \
3212 /* _argvec[0] holds current r2 across the call */ \
3213 _argvec[1] = (unsigned long)_orig.r2; \
3214 _argvec[2] = (unsigned long)_orig.nraddr; \
3215 _argvec[2+1] = (unsigned long)arg1; \
3216 _argvec[2+2] = (unsigned long)arg2; \
3217 _argvec[2+3] = (unsigned long)arg3; \
3218 _argvec[2+4] = (unsigned long)arg4; \
3219 _argvec[2+5] = (unsigned long)arg5; \
3220 _argvec[2+6] = (unsigned long)arg6; \
3221 _argvec[2+7] = (unsigned long)arg7; \
3222 __asm__ volatile( \
3223 "mr 11,%1\n\t" \
3224 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3225 "stw 2,-8(11)\n\t" /* save tocptr */ \
3226 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3227 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3228 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3229 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3230 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3231 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3232 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3233 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3234 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3235 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3236 "mr 11,%1\n\t" \
3237 "mr %0,3\n\t" \
3238 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3239 VG_CONTRACT_FRAME_BY(512) \
3240 : /*out*/ "=r" (_res) \
3241 : /*in*/ "r" (&_argvec[2]) \
3242 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3243 ); \
3244 lval = (__typeof__(lval)) _res; \
3245 } while (0)
3246
3247#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3248 arg7,arg8) \
3249 do { \
3250 volatile OrigFn _orig = (orig); \
3251 volatile unsigned long _argvec[3+8]; \
3252 volatile unsigned long _res; \
3253 /* _argvec[0] holds current r2 across the call */ \
3254 _argvec[1] = (unsigned long)_orig.r2; \
3255 _argvec[2] = (unsigned long)_orig.nraddr; \
3256 _argvec[2+1] = (unsigned long)arg1; \
3257 _argvec[2+2] = (unsigned long)arg2; \
3258 _argvec[2+3] = (unsigned long)arg3; \
3259 _argvec[2+4] = (unsigned long)arg4; \
3260 _argvec[2+5] = (unsigned long)arg5; \
3261 _argvec[2+6] = (unsigned long)arg6; \
3262 _argvec[2+7] = (unsigned long)arg7; \
3263 _argvec[2+8] = (unsigned long)arg8; \
3264 __asm__ volatile( \
3265 "mr 11,%1\n\t" \
3266 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3267 "stw 2,-8(11)\n\t" /* save tocptr */ \
3268 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3269 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3270 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3271 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3272 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3273 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3274 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3275 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3276 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3277 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3278 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3279 "mr 11,%1\n\t" \
3280 "mr %0,3\n\t" \
3281 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3282 VG_CONTRACT_FRAME_BY(512) \
3283 : /*out*/ "=r" (_res) \
3284 : /*in*/ "r" (&_argvec[2]) \
3285 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3286 ); \
3287 lval = (__typeof__(lval)) _res; \
3288 } while (0)
3289
3290#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3291 arg7,arg8,arg9) \
3292 do { \
3293 volatile OrigFn _orig = (orig); \
3294 volatile unsigned long _argvec[3+9]; \
3295 volatile unsigned long _res; \
3296 /* _argvec[0] holds current r2 across the call */ \
3297 _argvec[1] = (unsigned long)_orig.r2; \
3298 _argvec[2] = (unsigned long)_orig.nraddr; \
3299 _argvec[2+1] = (unsigned long)arg1; \
3300 _argvec[2+2] = (unsigned long)arg2; \
3301 _argvec[2+3] = (unsigned long)arg3; \
3302 _argvec[2+4] = (unsigned long)arg4; \
3303 _argvec[2+5] = (unsigned long)arg5; \
3304 _argvec[2+6] = (unsigned long)arg6; \
3305 _argvec[2+7] = (unsigned long)arg7; \
3306 _argvec[2+8] = (unsigned long)arg8; \
3307 _argvec[2+9] = (unsigned long)arg9; \
3308 __asm__ volatile( \
3309 "mr 11,%1\n\t" \
3310 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3311 "stw 2,-8(11)\n\t" /* save tocptr */ \
3312 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3313 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3314 /* arg9 */ \
3315 "lwz 3,36(11)\n\t" \
3316 "stw 3,56(1)\n\t" \
3317 /* args1-8 */ \
3318 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3319 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3320 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3321 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3322 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3323 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3324 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3325 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3326 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3327 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3328 "mr 11,%1\n\t" \
3329 "mr %0,3\n\t" \
3330 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3331 VG_CONTRACT_FRAME_BY(64) \
3332 VG_CONTRACT_FRAME_BY(512) \
3333 : /*out*/ "=r" (_res) \
3334 : /*in*/ "r" (&_argvec[2]) \
3335 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3336 ); \
3337 lval = (__typeof__(lval)) _res; \
3338 } while (0)
3339
3340#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3341 arg7,arg8,arg9,arg10) \
3342 do { \
3343 volatile OrigFn _orig = (orig); \
3344 volatile unsigned long _argvec[3+10]; \
3345 volatile unsigned long _res; \
3346 /* _argvec[0] holds current r2 across the call */ \
3347 _argvec[1] = (unsigned long)_orig.r2; \
3348 _argvec[2] = (unsigned long)_orig.nraddr; \
3349 _argvec[2+1] = (unsigned long)arg1; \
3350 _argvec[2+2] = (unsigned long)arg2; \
3351 _argvec[2+3] = (unsigned long)arg3; \
3352 _argvec[2+4] = (unsigned long)arg4; \
3353 _argvec[2+5] = (unsigned long)arg5; \
3354 _argvec[2+6] = (unsigned long)arg6; \
3355 _argvec[2+7] = (unsigned long)arg7; \
3356 _argvec[2+8] = (unsigned long)arg8; \
3357 _argvec[2+9] = (unsigned long)arg9; \
3358 _argvec[2+10] = (unsigned long)arg10; \
3359 __asm__ volatile( \
3360 "mr 11,%1\n\t" \
3361 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3362 "stw 2,-8(11)\n\t" /* save tocptr */ \
3363 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3364 VG_EXPAND_FRAME_BY_trashes_r3(64) \
3365 /* arg10 */ \
3366 "lwz 3,40(11)\n\t" \
3367 "stw 3,60(1)\n\t" \
3368 /* arg9 */ \
3369 "lwz 3,36(11)\n\t" \
3370 "stw 3,56(1)\n\t" \
3371 /* args1-8 */ \
3372 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3373 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3374 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3375 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3376 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3377 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3378 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3379 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3380 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3381 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3382 "mr 11,%1\n\t" \
3383 "mr %0,3\n\t" \
3384 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3385 VG_CONTRACT_FRAME_BY(64) \
3386 VG_CONTRACT_FRAME_BY(512) \
3387 : /*out*/ "=r" (_res) \
3388 : /*in*/ "r" (&_argvec[2]) \
3389 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3390 ); \
3391 lval = (__typeof__(lval)) _res; \
3392 } while (0)
3393
3394#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3395 arg7,arg8,arg9,arg10,arg11) \
3396 do { \
3397 volatile OrigFn _orig = (orig); \
3398 volatile unsigned long _argvec[3+11]; \
3399 volatile unsigned long _res; \
3400 /* _argvec[0] holds current r2 across the call */ \
3401 _argvec[1] = (unsigned long)_orig.r2; \
3402 _argvec[2] = (unsigned long)_orig.nraddr; \
3403 _argvec[2+1] = (unsigned long)arg1; \
3404 _argvec[2+2] = (unsigned long)arg2; \
3405 _argvec[2+3] = (unsigned long)arg3; \
3406 _argvec[2+4] = (unsigned long)arg4; \
3407 _argvec[2+5] = (unsigned long)arg5; \
3408 _argvec[2+6] = (unsigned long)arg6; \
3409 _argvec[2+7] = (unsigned long)arg7; \
3410 _argvec[2+8] = (unsigned long)arg8; \
3411 _argvec[2+9] = (unsigned long)arg9; \
3412 _argvec[2+10] = (unsigned long)arg10; \
3413 _argvec[2+11] = (unsigned long)arg11; \
3414 __asm__ volatile( \
3415 "mr 11,%1\n\t" \
3416 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3417 "stw 2,-8(11)\n\t" /* save tocptr */ \
3418 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3419 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3420 /* arg11 */ \
3421 "lwz 3,44(11)\n\t" \
3422 "stw 3,64(1)\n\t" \
3423 /* arg10 */ \
3424 "lwz 3,40(11)\n\t" \
3425 "stw 3,60(1)\n\t" \
3426 /* arg9 */ \
3427 "lwz 3,36(11)\n\t" \
3428 "stw 3,56(1)\n\t" \
3429 /* args1-8 */ \
3430 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3431 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3432 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3433 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3434 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3435 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3436 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3437 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3438 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3439 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3440 "mr 11,%1\n\t" \
3441 "mr %0,3\n\t" \
3442 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3443 VG_CONTRACT_FRAME_BY(72) \
3444 VG_CONTRACT_FRAME_BY(512) \
3445 : /*out*/ "=r" (_res) \
3446 : /*in*/ "r" (&_argvec[2]) \
3447 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3448 ); \
3449 lval = (__typeof__(lval)) _res; \
3450 } while (0)
3451
3452#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3453 arg7,arg8,arg9,arg10,arg11,arg12) \
3454 do { \
3455 volatile OrigFn _orig = (orig); \
3456 volatile unsigned long _argvec[3+12]; \
3457 volatile unsigned long _res; \
3458 /* _argvec[0] holds current r2 across the call */ \
3459 _argvec[1] = (unsigned long)_orig.r2; \
3460 _argvec[2] = (unsigned long)_orig.nraddr; \
3461 _argvec[2+1] = (unsigned long)arg1; \
3462 _argvec[2+2] = (unsigned long)arg2; \
3463 _argvec[2+3] = (unsigned long)arg3; \
3464 _argvec[2+4] = (unsigned long)arg4; \
3465 _argvec[2+5] = (unsigned long)arg5; \
3466 _argvec[2+6] = (unsigned long)arg6; \
3467 _argvec[2+7] = (unsigned long)arg7; \
3468 _argvec[2+8] = (unsigned long)arg8; \
3469 _argvec[2+9] = (unsigned long)arg9; \
3470 _argvec[2+10] = (unsigned long)arg10; \
3471 _argvec[2+11] = (unsigned long)arg11; \
3472 _argvec[2+12] = (unsigned long)arg12; \
3473 __asm__ volatile( \
3474 "mr 11,%1\n\t" \
3475 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3476 "stw 2,-8(11)\n\t" /* save tocptr */ \
3477 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
3478 VG_EXPAND_FRAME_BY_trashes_r3(72) \
3479 /* arg12 */ \
3480 "lwz 3,48(11)\n\t" \
3481 "stw 3,68(1)\n\t" \
3482 /* arg11 */ \
3483 "lwz 3,44(11)\n\t" \
3484 "stw 3,64(1)\n\t" \
3485 /* arg10 */ \
3486 "lwz 3,40(11)\n\t" \
3487 "stw 3,60(1)\n\t" \
3488 /* arg9 */ \
3489 "lwz 3,36(11)\n\t" \
3490 "stw 3,56(1)\n\t" \
3491 /* args1-8 */ \
3492 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
3493 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
3494 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
3495 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
3496 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
3497 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
3498 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
3499 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
3500 "lwz 11, 0(11)\n\t" /* target->r11 */ \
3501 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3502 "mr 11,%1\n\t" \
3503 "mr %0,3\n\t" \
3504 "lwz 2,-8(11)\n\t" /* restore tocptr */ \
3505 VG_CONTRACT_FRAME_BY(72) \
3506 VG_CONTRACT_FRAME_BY(512) \
3507 : /*out*/ "=r" (_res) \
3508 : /*in*/ "r" (&_argvec[2]) \
3509 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3510 ); \
3511 lval = (__typeof__(lval)) _res; \
3512 } while (0)
3513
3514#endif /* PLAT_ppc32_aix5 */
3515
3516/* ------------------------ ppc64-aix5 ------------------------- */
3517
3518#if defined(PLAT_ppc64_aix5)
3519
3520/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3521
3522/* These regs are trashed by the hidden call. */
3523#define __CALLER_SAVED_REGS \
3524 "lr", "ctr", "xer", \
3525 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
3526 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
3527 "r11", "r12", "r13"
3528
3529/* Expand the stack frame, copying enough info that unwinding
3530 still works. Trashes r3. */
3531
3532#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
3533 "addi 1,1,-" #_n_fr "\n\t" \
3534 "ld 3," #_n_fr "(1)\n\t" \
3535 "std 3,0(1)\n\t"
3536
3537#define VG_CONTRACT_FRAME_BY(_n_fr) \
3538 "addi 1,1," #_n_fr "\n\t"
3539
3540/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
3541 long) == 8. */
3542
3543#define CALL_FN_W_v(lval, orig) \
3544 do { \
3545 volatile OrigFn _orig = (orig); \
3546 volatile unsigned long _argvec[3+0]; \
3547 volatile unsigned long _res; \
3548 /* _argvec[0] holds current r2 across the call */ \
3549 _argvec[1] = (unsigned long)_orig.r2; \
3550 _argvec[2] = (unsigned long)_orig.nraddr; \
3551 __asm__ volatile( \
3552 "mr 11,%1\n\t" \
3553 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3554 "std 2,-16(11)\n\t" /* save tocptr */ \
3555 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3556 "ld 11, 0(11)\n\t" /* target->r11 */ \
3557 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3558 "mr 11,%1\n\t" \
3559 "mr %0,3\n\t" \
3560 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3561 VG_CONTRACT_FRAME_BY(512) \
3562 : /*out*/ "=r" (_res) \
3563 : /*in*/ "r" (&_argvec[2]) \
3564 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3565 ); \
3566 lval = (__typeof__(lval)) _res; \
3567 } while (0)
3568
3569#define CALL_FN_W_W(lval, orig, arg1) \
3570 do { \
3571 volatile OrigFn _orig = (orig); \
3572 volatile unsigned long _argvec[3+1]; \
3573 volatile unsigned long _res; \
3574 /* _argvec[0] holds current r2 across the call */ \
3575 _argvec[1] = (unsigned long)_orig.r2; \
3576 _argvec[2] = (unsigned long)_orig.nraddr; \
3577 _argvec[2+1] = (unsigned long)arg1; \
3578 __asm__ volatile( \
3579 "mr 11,%1\n\t" \
3580 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3581 "std 2,-16(11)\n\t" /* save tocptr */ \
3582 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3583 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3584 "ld 11, 0(11)\n\t" /* target->r11 */ \
3585 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3586 "mr 11,%1\n\t" \
3587 "mr %0,3\n\t" \
3588 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3589 VG_CONTRACT_FRAME_BY(512) \
3590 : /*out*/ "=r" (_res) \
3591 : /*in*/ "r" (&_argvec[2]) \
3592 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3593 ); \
3594 lval = (__typeof__(lval)) _res; \
3595 } while (0)
3596
3597#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
3598 do { \
3599 volatile OrigFn _orig = (orig); \
3600 volatile unsigned long _argvec[3+2]; \
3601 volatile unsigned long _res; \
3602 /* _argvec[0] holds current r2 across the call */ \
3603 _argvec[1] = (unsigned long)_orig.r2; \
3604 _argvec[2] = (unsigned long)_orig.nraddr; \
3605 _argvec[2+1] = (unsigned long)arg1; \
3606 _argvec[2+2] = (unsigned long)arg2; \
3607 __asm__ volatile( \
3608 "mr 11,%1\n\t" \
3609 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3610 "std 2,-16(11)\n\t" /* save tocptr */ \
3611 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3612 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3613 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3614 "ld 11, 0(11)\n\t" /* target->r11 */ \
3615 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3616 "mr 11,%1\n\t" \
3617 "mr %0,3\n\t" \
3618 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3619 VG_CONTRACT_FRAME_BY(512) \
3620 : /*out*/ "=r" (_res) \
3621 : /*in*/ "r" (&_argvec[2]) \
3622 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3623 ); \
3624 lval = (__typeof__(lval)) _res; \
3625 } while (0)
3626
3627#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
3628 do { \
3629 volatile OrigFn _orig = (orig); \
3630 volatile unsigned long _argvec[3+3]; \
3631 volatile unsigned long _res; \
3632 /* _argvec[0] holds current r2 across the call */ \
3633 _argvec[1] = (unsigned long)_orig.r2; \
3634 _argvec[2] = (unsigned long)_orig.nraddr; \
3635 _argvec[2+1] = (unsigned long)arg1; \
3636 _argvec[2+2] = (unsigned long)arg2; \
3637 _argvec[2+3] = (unsigned long)arg3; \
3638 __asm__ volatile( \
3639 "mr 11,%1\n\t" \
3640 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3641 "std 2,-16(11)\n\t" /* save tocptr */ \
3642 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3643 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3644 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3645 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3646 "ld 11, 0(11)\n\t" /* target->r11 */ \
3647 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3648 "mr 11,%1\n\t" \
3649 "mr %0,3\n\t" \
3650 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3651 VG_CONTRACT_FRAME_BY(512) \
3652 : /*out*/ "=r" (_res) \
3653 : /*in*/ "r" (&_argvec[2]) \
3654 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3655 ); \
3656 lval = (__typeof__(lval)) _res; \
3657 } while (0)
3658
3659#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
3660 do { \
3661 volatile OrigFn _orig = (orig); \
3662 volatile unsigned long _argvec[3+4]; \
3663 volatile unsigned long _res; \
3664 /* _argvec[0] holds current r2 across the call */ \
3665 _argvec[1] = (unsigned long)_orig.r2; \
3666 _argvec[2] = (unsigned long)_orig.nraddr; \
3667 _argvec[2+1] = (unsigned long)arg1; \
3668 _argvec[2+2] = (unsigned long)arg2; \
3669 _argvec[2+3] = (unsigned long)arg3; \
3670 _argvec[2+4] = (unsigned long)arg4; \
3671 __asm__ volatile( \
3672 "mr 11,%1\n\t" \
3673 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3674 "std 2,-16(11)\n\t" /* save tocptr */ \
3675 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3676 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3677 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3678 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3679 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3680 "ld 11, 0(11)\n\t" /* target->r11 */ \
3681 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3682 "mr 11,%1\n\t" \
3683 "mr %0,3\n\t" \
3684 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3685 VG_CONTRACT_FRAME_BY(512) \
3686 : /*out*/ "=r" (_res) \
3687 : /*in*/ "r" (&_argvec[2]) \
3688 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3689 ); \
3690 lval = (__typeof__(lval)) _res; \
3691 } while (0)
3692
3693#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
3694 do { \
3695 volatile OrigFn _orig = (orig); \
3696 volatile unsigned long _argvec[3+5]; \
3697 volatile unsigned long _res; \
3698 /* _argvec[0] holds current r2 across the call */ \
3699 _argvec[1] = (unsigned long)_orig.r2; \
3700 _argvec[2] = (unsigned long)_orig.nraddr; \
3701 _argvec[2+1] = (unsigned long)arg1; \
3702 _argvec[2+2] = (unsigned long)arg2; \
3703 _argvec[2+3] = (unsigned long)arg3; \
3704 _argvec[2+4] = (unsigned long)arg4; \
3705 _argvec[2+5] = (unsigned long)arg5; \
3706 __asm__ volatile( \
3707 "mr 11,%1\n\t" \
3708 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3709 "std 2,-16(11)\n\t" /* save tocptr */ \
3710 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3711 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3712 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3713 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3714 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3715 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3716 "ld 11, 0(11)\n\t" /* target->r11 */ \
3717 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3718 "mr 11,%1\n\t" \
3719 "mr %0,3\n\t" \
3720 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3721 VG_CONTRACT_FRAME_BY(512) \
3722 : /*out*/ "=r" (_res) \
3723 : /*in*/ "r" (&_argvec[2]) \
3724 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3725 ); \
3726 lval = (__typeof__(lval)) _res; \
3727 } while (0)
3728
3729#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
3730 do { \
3731 volatile OrigFn _orig = (orig); \
3732 volatile unsigned long _argvec[3+6]; \
3733 volatile unsigned long _res; \
3734 /* _argvec[0] holds current r2 across the call */ \
3735 _argvec[1] = (unsigned long)_orig.r2; \
3736 _argvec[2] = (unsigned long)_orig.nraddr; \
3737 _argvec[2+1] = (unsigned long)arg1; \
3738 _argvec[2+2] = (unsigned long)arg2; \
3739 _argvec[2+3] = (unsigned long)arg3; \
3740 _argvec[2+4] = (unsigned long)arg4; \
3741 _argvec[2+5] = (unsigned long)arg5; \
3742 _argvec[2+6] = (unsigned long)arg6; \
3743 __asm__ volatile( \
3744 "mr 11,%1\n\t" \
3745 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3746 "std 2,-16(11)\n\t" /* save tocptr */ \
3747 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3748 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3749 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3750 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3751 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3752 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3753 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3754 "ld 11, 0(11)\n\t" /* target->r11 */ \
3755 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3756 "mr 11,%1\n\t" \
3757 "mr %0,3\n\t" \
3758 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3759 VG_CONTRACT_FRAME_BY(512) \
3760 : /*out*/ "=r" (_res) \
3761 : /*in*/ "r" (&_argvec[2]) \
3762 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3763 ); \
3764 lval = (__typeof__(lval)) _res; \
3765 } while (0)
3766
3767#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3768 arg7) \
3769 do { \
3770 volatile OrigFn _orig = (orig); \
3771 volatile unsigned long _argvec[3+7]; \
3772 volatile unsigned long _res; \
3773 /* _argvec[0] holds current r2 across the call */ \
3774 _argvec[1] = (unsigned long)_orig.r2; \
3775 _argvec[2] = (unsigned long)_orig.nraddr; \
3776 _argvec[2+1] = (unsigned long)arg1; \
3777 _argvec[2+2] = (unsigned long)arg2; \
3778 _argvec[2+3] = (unsigned long)arg3; \
3779 _argvec[2+4] = (unsigned long)arg4; \
3780 _argvec[2+5] = (unsigned long)arg5; \
3781 _argvec[2+6] = (unsigned long)arg6; \
3782 _argvec[2+7] = (unsigned long)arg7; \
3783 __asm__ volatile( \
3784 "mr 11,%1\n\t" \
3785 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3786 "std 2,-16(11)\n\t" /* save tocptr */ \
3787 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3788 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3789 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3790 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3791 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3792 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3793 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3794 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3795 "ld 11, 0(11)\n\t" /* target->r11 */ \
3796 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3797 "mr 11,%1\n\t" \
3798 "mr %0,3\n\t" \
3799 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3800 VG_CONTRACT_FRAME_BY(512) \
3801 : /*out*/ "=r" (_res) \
3802 : /*in*/ "r" (&_argvec[2]) \
3803 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3804 ); \
3805 lval = (__typeof__(lval)) _res; \
3806 } while (0)
3807
3808#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3809 arg7,arg8) \
3810 do { \
3811 volatile OrigFn _orig = (orig); \
3812 volatile unsigned long _argvec[3+8]; \
3813 volatile unsigned long _res; \
3814 /* _argvec[0] holds current r2 across the call */ \
3815 _argvec[1] = (unsigned long)_orig.r2; \
3816 _argvec[2] = (unsigned long)_orig.nraddr; \
3817 _argvec[2+1] = (unsigned long)arg1; \
3818 _argvec[2+2] = (unsigned long)arg2; \
3819 _argvec[2+3] = (unsigned long)arg3; \
3820 _argvec[2+4] = (unsigned long)arg4; \
3821 _argvec[2+5] = (unsigned long)arg5; \
3822 _argvec[2+6] = (unsigned long)arg6; \
3823 _argvec[2+7] = (unsigned long)arg7; \
3824 _argvec[2+8] = (unsigned long)arg8; \
3825 __asm__ volatile( \
3826 "mr 11,%1\n\t" \
3827 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3828 "std 2,-16(11)\n\t" /* save tocptr */ \
3829 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3830 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3831 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3832 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3833 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3834 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3835 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3836 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3837 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3838 "ld 11, 0(11)\n\t" /* target->r11 */ \
3839 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3840 "mr 11,%1\n\t" \
3841 "mr %0,3\n\t" \
3842 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3843 VG_CONTRACT_FRAME_BY(512) \
3844 : /*out*/ "=r" (_res) \
3845 : /*in*/ "r" (&_argvec[2]) \
3846 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3847 ); \
3848 lval = (__typeof__(lval)) _res; \
3849 } while (0)
3850
3851#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3852 arg7,arg8,arg9) \
3853 do { \
3854 volatile OrigFn _orig = (orig); \
3855 volatile unsigned long _argvec[3+9]; \
3856 volatile unsigned long _res; \
3857 /* _argvec[0] holds current r2 across the call */ \
3858 _argvec[1] = (unsigned long)_orig.r2; \
3859 _argvec[2] = (unsigned long)_orig.nraddr; \
3860 _argvec[2+1] = (unsigned long)arg1; \
3861 _argvec[2+2] = (unsigned long)arg2; \
3862 _argvec[2+3] = (unsigned long)arg3; \
3863 _argvec[2+4] = (unsigned long)arg4; \
3864 _argvec[2+5] = (unsigned long)arg5; \
3865 _argvec[2+6] = (unsigned long)arg6; \
3866 _argvec[2+7] = (unsigned long)arg7; \
3867 _argvec[2+8] = (unsigned long)arg8; \
3868 _argvec[2+9] = (unsigned long)arg9; \
3869 __asm__ volatile( \
3870 "mr 11,%1\n\t" \
3871 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3872 "std 2,-16(11)\n\t" /* save tocptr */ \
3873 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3874 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3875 /* arg9 */ \
3876 "ld 3,72(11)\n\t" \
3877 "std 3,112(1)\n\t" \
3878 /* args1-8 */ \
3879 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3880 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3881 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3882 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3883 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3884 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3885 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3886 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3887 "ld 11, 0(11)\n\t" /* target->r11 */ \
3888 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3889 "mr 11,%1\n\t" \
3890 "mr %0,3\n\t" \
3891 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3892 VG_CONTRACT_FRAME_BY(128) \
3893 VG_CONTRACT_FRAME_BY(512) \
3894 : /*out*/ "=r" (_res) \
3895 : /*in*/ "r" (&_argvec[2]) \
3896 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3897 ); \
3898 lval = (__typeof__(lval)) _res; \
3899 } while (0)
3900
3901#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3902 arg7,arg8,arg9,arg10) \
3903 do { \
3904 volatile OrigFn _orig = (orig); \
3905 volatile unsigned long _argvec[3+10]; \
3906 volatile unsigned long _res; \
3907 /* _argvec[0] holds current r2 across the call */ \
3908 _argvec[1] = (unsigned long)_orig.r2; \
3909 _argvec[2] = (unsigned long)_orig.nraddr; \
3910 _argvec[2+1] = (unsigned long)arg1; \
3911 _argvec[2+2] = (unsigned long)arg2; \
3912 _argvec[2+3] = (unsigned long)arg3; \
3913 _argvec[2+4] = (unsigned long)arg4; \
3914 _argvec[2+5] = (unsigned long)arg5; \
3915 _argvec[2+6] = (unsigned long)arg6; \
3916 _argvec[2+7] = (unsigned long)arg7; \
3917 _argvec[2+8] = (unsigned long)arg8; \
3918 _argvec[2+9] = (unsigned long)arg9; \
3919 _argvec[2+10] = (unsigned long)arg10; \
3920 __asm__ volatile( \
3921 "mr 11,%1\n\t" \
3922 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3923 "std 2,-16(11)\n\t" /* save tocptr */ \
3924 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3925 VG_EXPAND_FRAME_BY_trashes_r3(128) \
3926 /* arg10 */ \
3927 "ld 3,80(11)\n\t" \
3928 "std 3,120(1)\n\t" \
3929 /* arg9 */ \
3930 "ld 3,72(11)\n\t" \
3931 "std 3,112(1)\n\t" \
3932 /* args1-8 */ \
3933 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3934 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3935 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3936 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3937 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3938 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3939 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3940 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3941 "ld 11, 0(11)\n\t" /* target->r11 */ \
3942 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
3943 "mr 11,%1\n\t" \
3944 "mr %0,3\n\t" \
3945 "ld 2,-16(11)\n\t" /* restore tocptr */ \
3946 VG_CONTRACT_FRAME_BY(128) \
3947 VG_CONTRACT_FRAME_BY(512) \
3948 : /*out*/ "=r" (_res) \
3949 : /*in*/ "r" (&_argvec[2]) \
3950 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
3951 ); \
3952 lval = (__typeof__(lval)) _res; \
3953 } while (0)
3954
3955#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
3956 arg7,arg8,arg9,arg10,arg11) \
3957 do { \
3958 volatile OrigFn _orig = (orig); \
3959 volatile unsigned long _argvec[3+11]; \
3960 volatile unsigned long _res; \
3961 /* _argvec[0] holds current r2 across the call */ \
3962 _argvec[1] = (unsigned long)_orig.r2; \
3963 _argvec[2] = (unsigned long)_orig.nraddr; \
3964 _argvec[2+1] = (unsigned long)arg1; \
3965 _argvec[2+2] = (unsigned long)arg2; \
3966 _argvec[2+3] = (unsigned long)arg3; \
3967 _argvec[2+4] = (unsigned long)arg4; \
3968 _argvec[2+5] = (unsigned long)arg5; \
3969 _argvec[2+6] = (unsigned long)arg6; \
3970 _argvec[2+7] = (unsigned long)arg7; \
3971 _argvec[2+8] = (unsigned long)arg8; \
3972 _argvec[2+9] = (unsigned long)arg9; \
3973 _argvec[2+10] = (unsigned long)arg10; \
3974 _argvec[2+11] = (unsigned long)arg11; \
3975 __asm__ volatile( \
3976 "mr 11,%1\n\t" \
3977 VG_EXPAND_FRAME_BY_trashes_r3(512) \
3978 "std 2,-16(11)\n\t" /* save tocptr */ \
3979 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
3980 VG_EXPAND_FRAME_BY_trashes_r3(144) \
3981 /* arg11 */ \
3982 "ld 3,88(11)\n\t" \
3983 "std 3,128(1)\n\t" \
3984 /* arg10 */ \
3985 "ld 3,80(11)\n\t" \
3986 "std 3,120(1)\n\t" \
3987 /* arg9 */ \
3988 "ld 3,72(11)\n\t" \
3989 "std 3,112(1)\n\t" \
3990 /* args1-8 */ \
3991 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
3992 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
3993 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
3994 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
3995 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
3996 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
3997 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
3998 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
3999 "ld 11, 0(11)\n\t" /* target->r11 */ \
4000 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4001 "mr 11,%1\n\t" \
4002 "mr %0,3\n\t" \
4003 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4004 VG_CONTRACT_FRAME_BY(144) \
4005 VG_CONTRACT_FRAME_BY(512) \
4006 : /*out*/ "=r" (_res) \
4007 : /*in*/ "r" (&_argvec[2]) \
4008 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4009 ); \
4010 lval = (__typeof__(lval)) _res; \
4011 } while (0)
4012
4013#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
4014 arg7,arg8,arg9,arg10,arg11,arg12) \
4015 do { \
4016 volatile OrigFn _orig = (orig); \
4017 volatile unsigned long _argvec[3+12]; \
4018 volatile unsigned long _res; \
4019 /* _argvec[0] holds current r2 across the call */ \
4020 _argvec[1] = (unsigned long)_orig.r2; \
4021 _argvec[2] = (unsigned long)_orig.nraddr; \
4022 _argvec[2+1] = (unsigned long)arg1; \
4023 _argvec[2+2] = (unsigned long)arg2; \
4024 _argvec[2+3] = (unsigned long)arg3; \
4025 _argvec[2+4] = (unsigned long)arg4; \
4026 _argvec[2+5] = (unsigned long)arg5; \
4027 _argvec[2+6] = (unsigned long)arg6; \
4028 _argvec[2+7] = (unsigned long)arg7; \
4029 _argvec[2+8] = (unsigned long)arg8; \
4030 _argvec[2+9] = (unsigned long)arg9; \
4031 _argvec[2+10] = (unsigned long)arg10; \
4032 _argvec[2+11] = (unsigned long)arg11; \
4033 _argvec[2+12] = (unsigned long)arg12; \
4034 __asm__ volatile( \
4035 "mr 11,%1\n\t" \
4036 VG_EXPAND_FRAME_BY_trashes_r3(512) \
4037 "std 2,-16(11)\n\t" /* save tocptr */ \
4038 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
4039 VG_EXPAND_FRAME_BY_trashes_r3(144) \
4040 /* arg12 */ \
4041 "ld 3,96(11)\n\t" \
4042 "std 3,136(1)\n\t" \
4043 /* arg11 */ \
4044 "ld 3,88(11)\n\t" \
4045 "std 3,128(1)\n\t" \
4046 /* arg10 */ \
4047 "ld 3,80(11)\n\t" \
4048 "std 3,120(1)\n\t" \
4049 /* arg9 */ \
4050 "ld 3,72(11)\n\t" \
4051 "std 3,112(1)\n\t" \
4052 /* args1-8 */ \
4053 "ld 3, 8(11)\n\t" /* arg1->r3 */ \
4054 "ld 4, 16(11)\n\t" /* arg2->r4 */ \
4055 "ld 5, 24(11)\n\t" /* arg3->r5 */ \
4056 "ld 6, 32(11)\n\t" /* arg4->r6 */ \
4057 "ld 7, 40(11)\n\t" /* arg5->r7 */ \
4058 "ld 8, 48(11)\n\t" /* arg6->r8 */ \
4059 "ld 9, 56(11)\n\t" /* arg7->r9 */ \
4060 "ld 10, 64(11)\n\t" /* arg8->r10 */ \
4061 "ld 11, 0(11)\n\t" /* target->r11 */ \
4062 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
4063 "mr 11,%1\n\t" \
4064 "mr %0,3\n\t" \
4065 "ld 2,-16(11)\n\t" /* restore tocptr */ \
4066 VG_CONTRACT_FRAME_BY(144) \
4067 VG_CONTRACT_FRAME_BY(512) \
4068 : /*out*/ "=r" (_res) \
4069 : /*in*/ "r" (&_argvec[2]) \
4070 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
4071 ); \
4072 lval = (__typeof__(lval)) _res; \
4073 } while (0)
4074
4075#endif /* PLAT_ppc64_aix5 */
sewardj9734b202006-01-17 01:49:37 +00004076
sewardj0ec07f32006-01-12 12:32:32 +00004077
4078/* ------------------------------------------------------------------ */
4079/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
4080/* */
njn30d76c62005-06-18 15:07:39 +00004081/* ------------------------------------------------------------------ */
4082
sewardj2e93c502002-04-12 11:12:52 +00004083/* Some request codes. There are many more of these, but most are not
4084 exposed to end-user view. These are the public ones, all of the
njn25e49d8e72002-09-23 09:36:25 +00004085 form 0x1000 + small_number.
njnd7994182003-10-02 13:44:04 +00004086
sewardj0ec07f32006-01-12 12:32:32 +00004087 Core ones are in the range 0x00000000--0x0000ffff. The non-public
4088 ones start at 0x2000.
sewardj2e93c502002-04-12 11:12:52 +00004089*/
4090
sewardj0ec07f32006-01-12 12:32:32 +00004091/* These macros are used by tools -- they must be public, but don't
4092 embed them into other programs. */
njnfc26ff92004-11-22 19:12:49 +00004093#define VG_USERREQ_TOOL_BASE(a,b) \
njn4c791212003-05-02 17:53:54 +00004094 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
njnfc26ff92004-11-22 19:12:49 +00004095#define VG_IS_TOOL_USERREQ(a, b, v) \
4096 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
sewardj34042512002-10-22 04:14:35 +00004097
sewardj5ce4b152006-03-11 12:57:41 +00004098/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
4099 This enum comprises an ABI exported by Valgrind to programs
4100 which use client requests. DO NOT CHANGE THE ORDER OF THESE
4101 ENTRIES, NOR DELETE ANY -- add new ones at the end. */
njn25e49d8e72002-09-23 09:36:25 +00004102typedef
njn4c791212003-05-02 17:53:54 +00004103 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
4104 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
njn3e884182003-04-15 13:03:23 +00004105
sewardj0ec07f32006-01-12 12:32:32 +00004106 /* These allow any function to be called from the simulated
4107 CPU but run on the real CPU. Nb: the first arg passed to
4108 the function is always the ThreadId of the running
4109 thread! So CLIENT_CALL0 actually requires a 1 arg
njnd4795be2004-11-24 11:57:51 +00004110 function, etc. */
njn4c791212003-05-02 17:53:54 +00004111 VG_USERREQ__CLIENT_CALL0 = 0x1101,
4112 VG_USERREQ__CLIENT_CALL1 = 0x1102,
4113 VG_USERREQ__CLIENT_CALL2 = 0x1103,
4114 VG_USERREQ__CLIENT_CALL3 = 0x1104,
njn3e884182003-04-15 13:03:23 +00004115
sewardj0ec07f32006-01-12 12:32:32 +00004116 /* Can be useful in regression testing suites -- eg. can
4117 send Valgrind's output to /dev/null and still count
4118 errors. */
njn4c791212003-05-02 17:53:54 +00004119 VG_USERREQ__COUNT_ERRORS = 0x1201,
njn47363ab2003-04-21 13:24:40 +00004120
sewardj0ec07f32006-01-12 12:32:32 +00004121 /* These are useful and can be interpreted by any tool that
4122 tracks malloc() et al, by using vg_replace_malloc.c. */
njnd7994182003-10-02 13:44:04 +00004123 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
4124 VG_USERREQ__FREELIKE_BLOCK = 0x1302,
rjwalshbc0bb832004-06-19 18:12:36 +00004125 /* Memory pool support. */
4126 VG_USERREQ__CREATE_MEMPOOL = 0x1303,
4127 VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
4128 VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
4129 VG_USERREQ__MEMPOOL_FREE = 0x1306,
sewardj2c1c9df2006-07-28 00:06:37 +00004130 VG_USERREQ__MEMPOOL_TRIM = 0x1307,
sewardjc740d762006-10-05 17:59:23 +00004131 VG_USERREQ__MOVE_MEMPOOL = 0x1308,
4132 VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
4133 VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
njnd7994182003-10-02 13:44:04 +00004134
fitzhardinge39de4b42003-10-31 07:12:21 +00004135 /* Allow printfs to valgrind log. */
sewardjc560fb32010-01-28 15:23:54 +00004136 /* The first two pass the va_list argument by value, which
4137 assumes it is the same size as or smaller than a UWord,
4138 which generally isn't the case. Hence are deprecated.
4139 The second two pass the vargs by reference and so are
4140 immune to this problem. */
4141 /* both :: char* fmt, va_list vargs (DEPRECATED) */
njn30d76c62005-06-18 15:07:39 +00004142 VG_USERREQ__PRINTF = 0x1401,
rjwalsh0140af52005-06-04 20:42:33 +00004143 VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
sewardjc560fb32010-01-28 15:23:54 +00004144 /* both :: char* fmt, va_list* vargs */
4145 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
4146 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
rjwalsh0140af52005-06-04 20:42:33 +00004147
4148 /* Stack support. */
4149 VG_USERREQ__STACK_REGISTER = 0x1501,
4150 VG_USERREQ__STACK_DEREGISTER = 0x1502,
sewardjc8259b82009-04-22 22:42:10 +00004151 VG_USERREQ__STACK_CHANGE = 0x1503,
4152
4153 /* Wine support */
4154 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601
njn25e49d8e72002-09-23 09:36:25 +00004155 } Vg_ClientRequest;
sewardj2e93c502002-04-12 11:12:52 +00004156
sewardj0ec07f32006-01-12 12:32:32 +00004157#if !defined(__GNUC__)
4158# define __extension__ /* */
muellerc9b36552003-12-31 14:32:23 +00004159#endif
sewardj2e93c502002-04-12 11:12:52 +00004160
sewardj0ec07f32006-01-12 12:32:32 +00004161/* Returns the number of Valgrinds this code is running under. That
4162 is, 0 if running natively, 1 if running under Valgrind, 2 if
4163 running under Valgrind which is running under another Valgrind,
4164 etc. */
4165#define RUNNING_ON_VALGRIND __extension__ \
4166 ({unsigned int _qzz_res; \
4167 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \
4168 VG_USERREQ__RUNNING_ON_VALGRIND, \
sewardj9af10a12006-02-01 14:59:42 +00004169 0, 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004170 _qzz_res; \
sewardjde4a1d02002-03-22 01:27:54 +00004171 })
4172
4173
sewardj18d75132002-05-16 11:06:21 +00004174/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
4175 _qzz_len - 1]. Useful if you are debugging a JITter or some such,
4176 since it provides a way to make sure valgrind will retranslate the
4177 invalidated area. Returns no value. */
sewardj0ec07f32006-01-12 12:32:32 +00004178#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
4179 {unsigned int _qzz_res; \
4180 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4181 VG_USERREQ__DISCARD_TRANSLATIONS, \
sewardj9af10a12006-02-01 14:59:42 +00004182 _qzz_addr, _qzz_len, 0, 0, 0); \
sewardj18d75132002-05-16 11:06:21 +00004183 }
4184
njn26aba4d2005-05-16 13:31:23 +00004185
sewardj0ec07f32006-01-12 12:32:32 +00004186/* These requests are for getting Valgrind itself to print something.
njnd55f0d92009-08-03 01:38:56 +00004187 Possibly with a backtrace. This is a really ugly hack. The return value
4188 is the number of characters printed, excluding the "**<pid>** " part at the
4189 start and the backtrace (if present). */
sewardj0ec07f32006-01-12 12:32:32 +00004190
4191#if defined(NVALGRIND)
4192
4193# define VALGRIND_PRINTF(...)
4194# define VALGRIND_PRINTF_BACKTRACE(...)
njn26aba4d2005-05-16 13:31:23 +00004195
4196#else /* NVALGRIND */
fitzhardinge39de4b42003-10-31 07:12:21 +00004197
sewardj7eca0cc2006-04-12 17:15:35 +00004198/* Modern GCC will optimize the static routine out if unused,
4199 and unused attribute will shut down warnings about it. */
4200static int VALGRIND_PRINTF(const char *format, ...)
4201 __attribute__((format(__printf__, 1, 2), __unused__));
4202static int
fitzhardingea09a1b52003-11-07 23:09:48 +00004203VALGRIND_PRINTF(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00004204{
njnc6168192004-11-29 13:54:10 +00004205 unsigned long _qzz_res;
sewardjc560fb32010-01-28 15:23:54 +00004206 va_list vargs;
4207 va_start(vargs, format);
4208 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4209 VG_USERREQ__PRINTF_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00004210 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00004211 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00004212 0, 0, 0);
sewardjc560fb32010-01-28 15:23:54 +00004213 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00004214 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00004215}
4216
sewardj7eca0cc2006-04-12 17:15:35 +00004217static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
4218 __attribute__((format(__printf__, 1, 2), __unused__));
4219static int
fitzhardingea09a1b52003-11-07 23:09:48 +00004220VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
fitzhardinge39de4b42003-10-31 07:12:21 +00004221{
njnc6168192004-11-29 13:54:10 +00004222 unsigned long _qzz_res;
sewardjc560fb32010-01-28 15:23:54 +00004223 va_list vargs;
4224 va_start(vargs, format);
4225 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
4226 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
sewardj05b07152010-01-04 01:01:02 +00004227 (unsigned long)format,
sewardjc560fb32010-01-28 15:23:54 +00004228 (unsigned long)&vargs,
sewardj9af10a12006-02-01 14:59:42 +00004229 0, 0, 0);
sewardjc560fb32010-01-28 15:23:54 +00004230 va_end(vargs);
njnc6168192004-11-29 13:54:10 +00004231 return (int)_qzz_res;
fitzhardinge39de4b42003-10-31 07:12:21 +00004232}
4233
fitzhardinge39de4b42003-10-31 07:12:21 +00004234#endif /* NVALGRIND */
sewardj18d75132002-05-16 11:06:21 +00004235
sewardj0ec07f32006-01-12 12:32:32 +00004236
njn3e884182003-04-15 13:03:23 +00004237/* These requests allow control to move from the simulated CPU to the
njn1319b492006-11-20 22:02:40 +00004238 real CPU, calling an arbitary function.
4239
4240 Note that the current ThreadId is inserted as the first argument.
4241 So this call:
4242
4243 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
4244
4245 requires f to have this signature:
4246
4247 Word f(Word tid, Word arg1, Word arg2)
4248
4249 where "Word" is a word-sized type.
njn45fb4d32007-12-05 21:51:50 +00004250
4251 Note that these client requests are not entirely reliable. For example,
4252 if you call a function with them that subsequently calls printf(),
4253 there's a high chance Valgrind will crash. Generally, your prospects of
4254 these working are made higher if the called function does not refer to
4255 any global variables, and does not refer to any libc or other functions
4256 (printf et al). Any kind of entanglement with libc or dynamic linking is
4257 likely to have a bad outcome, for tricky reasons which we've grappled
4258 with a lot in the past.
njn1319b492006-11-20 22:02:40 +00004259*/
sewardj0ec07f32006-01-12 12:32:32 +00004260#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
sewardj315dc8d2006-08-28 21:13:06 +00004261 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004262 ({unsigned long _qyy_res; \
4263 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4264 VG_USERREQ__CLIENT_CALL0, \
4265 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004266 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004267 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004268 })
4269
sewardj0ec07f32006-01-12 12:32:32 +00004270#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
sewardj315dc8d2006-08-28 21:13:06 +00004271 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004272 ({unsigned long _qyy_res; \
4273 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4274 VG_USERREQ__CLIENT_CALL1, \
4275 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004276 _qyy_arg1, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004277 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004278 })
4279
sewardj0ec07f32006-01-12 12:32:32 +00004280#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
sewardj315dc8d2006-08-28 21:13:06 +00004281 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004282 ({unsigned long _qyy_res; \
4283 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4284 VG_USERREQ__CLIENT_CALL2, \
4285 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004286 _qyy_arg1, _qyy_arg2, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004287 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004288 })
4289
sewardj0ec07f32006-01-12 12:32:32 +00004290#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
sewardj315dc8d2006-08-28 21:13:06 +00004291 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004292 ({unsigned long _qyy_res; \
4293 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4294 VG_USERREQ__CLIENT_CALL3, \
4295 _qyy_fn, \
sewardj9af10a12006-02-01 14:59:42 +00004296 _qyy_arg1, _qyy_arg2, \
4297 _qyy_arg3, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004298 _qyy_res; \
njn3e884182003-04-15 13:03:23 +00004299 })
4300
4301
nethercote7cc9c232004-01-21 15:08:04 +00004302/* Counts the number of errors that have been recorded by a tool. Nb:
4303 the tool must record the errors with VG_(maybe_record_error)() or
njn47363ab2003-04-21 13:24:40 +00004304 VG_(unique_error)() for them to be counted. */
sewardj0ec07f32006-01-12 12:32:32 +00004305#define VALGRIND_COUNT_ERRORS \
sewardj315dc8d2006-08-28 21:13:06 +00004306 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004307 ({unsigned int _qyy_res; \
4308 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
4309 VG_USERREQ__COUNT_ERRORS, \
sewardj9af10a12006-02-01 14:59:42 +00004310 0, 0, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004311 _qyy_res; \
njn47363ab2003-04-21 13:24:40 +00004312 })
4313
njn3ac96952009-07-09 23:35:44 +00004314/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
4315 when heap blocks are allocated in order to give accurate results. This
4316 happens automatically for the standard allocator functions such as
4317 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
4318 delete[], etc.
njnd7994182003-10-02 13:44:04 +00004319
njn3ac96952009-07-09 23:35:44 +00004320 But if your program uses a custom allocator, this doesn't automatically
4321 happen, and Valgrind will not do as well. For example, if you allocate
4322 superblocks with mmap() and then allocates chunks of the superblocks, all
4323 Valgrind's observations will be at the mmap() level and it won't know that
4324 the chunks should be considered separate entities. In Memcheck's case,
4325 that means you probably won't get heap block overrun detection (because
4326 there won't be redzones marked as unaddressable) and you definitely won't
4327 get any leak detection.
4328
4329 The following client requests allow a custom allocator to be annotated so
4330 that it can be handled accurately by Valgrind.
4331
4332 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
4333 by a malloc()-like function. For Memcheck (an illustrative case), this
4334 does two things:
4335
4336 - It records that the block has been allocated. This means any addresses
4337 within the block mentioned in error messages will be
4338 identified as belonging to the block. It also means that if the block
4339 isn't freed it will be detected by the leak checker.
4340
4341 - It marks the block as being addressable and undefined (if 'is_zeroed' is
4342 not set), or addressable and defined (if 'is_zeroed' is set). This
4343 controls how accesses to the block by the program are handled.
4344
4345 'addr' is the start of the usable block (ie. after any
4346 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
4347 can apply redzones -- these are blocks of padding at the start and end of
4348 each block. Adding redzones is recommended as it makes it much more likely
4349 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
4350 zeroed (or filled with another predictable value), as is the case for
4351 calloc().
4352
4353 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
4354 heap block -- that will be used by the client program -- is allocated.
4355 It's best to put it at the outermost level of the allocator if possible;
4356 for example, if you have a function my_alloc() which calls
4357 internal_alloc(), and the client request is put inside internal_alloc(),
4358 stack traces relating to the heap block will contain entries for both
4359 my_alloc() and internal_alloc(), which is probably not what you want.
4360
njnb965efb2009-08-10 07:36:54 +00004361 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
4362 custom blocks from within a heap block, B, that has been allocated with
4363 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
4364 -- the custom blocks will take precedence.
4365
njn3ac96952009-07-09 23:35:44 +00004366 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
4367 Memcheck, it does two things:
4368
4369 - It records that the block has been deallocated. This assumes that the
4370 block was annotated as having been allocated via
4371 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
4372
4373 - It marks the block as being unaddressable.
4374
4375 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
4376 heap block is deallocated.
4377
4378 In many cases, these two client requests will not be enough to get your
4379 allocator working well with Memcheck. More specifically, if your allocator
4380 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
4381 will be necessary to mark the memory as addressable just before the zeroing
4382 occurs, otherwise you'll get a lot of invalid write errors. For example,
4383 you'll need to do this if your allocator recycles freed blocks, but it
4384 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
4385 Alternatively, if your allocator reuses freed blocks for allocator-internal
4386 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
4387
4388 Really, what's happening is a blurring of the lines between the client
4389 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
4390 memory should be considered unaddressable to the client program, but the
4391 allocator knows more than the rest of the client program and so may be able
4392 to safely access it. Extra client requests are necessary for Valgrind to
4393 understand the distinction between the allocator and the rest of the
4394 program.
4395
4396 Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it
4397 has to be emulated with MALLOCLIKE/FREELIKE and memory copying.
4398
njn32f8d8c2009-07-15 02:31:45 +00004399 Ignored if addr == 0.
njn3ac96952009-07-09 23:35:44 +00004400*/
sewardj0ec07f32006-01-12 12:32:32 +00004401#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
4402 {unsigned int _qzz_res; \
4403 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4404 VG_USERREQ__MALLOCLIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00004405 addr, sizeB, rzB, is_zeroed, 0); \
njnd7994182003-10-02 13:44:04 +00004406 }
4407
njn32f8d8c2009-07-15 02:31:45 +00004408/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
4409 Ignored if addr == 0.
4410*/
sewardj0ec07f32006-01-12 12:32:32 +00004411#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
4412 {unsigned int _qzz_res; \
4413 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4414 VG_USERREQ__FREELIKE_BLOCK, \
sewardj9af10a12006-02-01 14:59:42 +00004415 addr, rzB, 0, 0, 0); \
njnd7994182003-10-02 13:44:04 +00004416 }
4417
rjwalshbc0bb832004-06-19 18:12:36 +00004418/* Create a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004419#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
4420 {unsigned int _qzz_res; \
4421 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4422 VG_USERREQ__CREATE_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00004423 pool, rzB, is_zeroed, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004424 }
4425
4426/* Destroy a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004427#define VALGRIND_DESTROY_MEMPOOL(pool) \
4428 {unsigned int _qzz_res; \
4429 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4430 VG_USERREQ__DESTROY_MEMPOOL, \
sewardj9af10a12006-02-01 14:59:42 +00004431 pool, 0, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004432 }
4433
4434/* Associate a piece of memory with a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004435#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
4436 {unsigned int _qzz_res; \
4437 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4438 VG_USERREQ__MEMPOOL_ALLOC, \
sewardj9af10a12006-02-01 14:59:42 +00004439 pool, addr, size, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004440 }
4441
4442/* Disassociate a piece of memory from a memory pool. */
sewardj0ec07f32006-01-12 12:32:32 +00004443#define VALGRIND_MEMPOOL_FREE(pool, addr) \
4444 {unsigned int _qzz_res; \
4445 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4446 VG_USERREQ__MEMPOOL_FREE, \
sewardj9af10a12006-02-01 14:59:42 +00004447 pool, addr, 0, 0, 0); \
rjwalshbc0bb832004-06-19 18:12:36 +00004448 }
4449
sewardj2c1c9df2006-07-28 00:06:37 +00004450/* Disassociate any pieces outside a particular range. */
4451#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
4452 {unsigned int _qzz_res; \
4453 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4454 VG_USERREQ__MEMPOOL_TRIM, \
4455 pool, addr, size, 0, 0); \
4456 }
4457
sewardjc740d762006-10-05 17:59:23 +00004458/* Resize and/or move a piece associated with a memory pool. */
4459#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
4460 {unsigned int _qzz_res; \
4461 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4462 VG_USERREQ__MOVE_MEMPOOL, \
4463 poolA, poolB, 0, 0, 0); \
4464 }
4465
4466/* Resize and/or move a piece associated with a memory pool. */
4467#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
4468 {unsigned int _qzz_res; \
4469 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4470 VG_USERREQ__MEMPOOL_CHANGE, \
4471 pool, addrA, addrB, size, 0); \
4472 }
4473
4474/* Return 1 if a mempool exists, else 0. */
4475#define VALGRIND_MEMPOOL_EXISTS(pool) \
njn44862972009-02-23 02:08:24 +00004476 __extension__ \
sewardjc740d762006-10-05 17:59:23 +00004477 ({unsigned int _qzz_res; \
4478 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4479 VG_USERREQ__MEMPOOL_EXISTS, \
4480 pool, 0, 0, 0, 0); \
4481 _qzz_res; \
4482 })
4483
rjwalsh0140af52005-06-04 20:42:33 +00004484/* Mark a piece of memory as being a stack. Returns a stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004485#define VALGRIND_STACK_REGISTER(start, end) \
njn44862972009-02-23 02:08:24 +00004486 __extension__ \
sewardj0ec07f32006-01-12 12:32:32 +00004487 ({unsigned int _qzz_res; \
4488 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4489 VG_USERREQ__STACK_REGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00004490 start, end, 0, 0, 0); \
sewardj0ec07f32006-01-12 12:32:32 +00004491 _qzz_res; \
rjwalsh0140af52005-06-04 20:42:33 +00004492 })
4493
4494/* Unmark the piece of memory associated with a stack id as being a
4495 stack. */
sewardj0ec07f32006-01-12 12:32:32 +00004496#define VALGRIND_STACK_DEREGISTER(id) \
4497 {unsigned int _qzz_res; \
4498 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4499 VG_USERREQ__STACK_DEREGISTER, \
sewardj9af10a12006-02-01 14:59:42 +00004500 id, 0, 0, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00004501 }
4502
4503/* Change the start and end address of the stack id. */
sewardj0ec07f32006-01-12 12:32:32 +00004504#define VALGRIND_STACK_CHANGE(id, start, end) \
4505 {unsigned int _qzz_res; \
4506 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4507 VG_USERREQ__STACK_CHANGE, \
sewardj9af10a12006-02-01 14:59:42 +00004508 id, start, end, 0, 0); \
rjwalsh0140af52005-06-04 20:42:33 +00004509 }
4510
sewardjc8259b82009-04-22 22:42:10 +00004511/* Load PDB debug info for Wine PE image_map. */
4512#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
4513 {unsigned int _qzz_res; \
4514 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
4515 VG_USERREQ__LOAD_PDB_DEBUGINFO, \
4516 fd, ptr, total_size, delta, 0); \
4517 }
4518
sewardj0ec07f32006-01-12 12:32:32 +00004519
sewardjf5c1a7f2006-10-17 01:32:48 +00004520#undef PLAT_x86_linux
4521#undef PLAT_amd64_linux
4522#undef PLAT_ppc32_linux
4523#undef PLAT_ppc64_linux
sewardj59570ff2010-01-01 11:59:33 +00004524#undef PLAT_arm_linux
sewardjf5c1a7f2006-10-17 01:32:48 +00004525#undef PLAT_ppc32_aix5
4526#undef PLAT_ppc64_aix5
sewardj0ec07f32006-01-12 12:32:32 +00004527
njn3e884182003-04-15 13:03:23 +00004528#endif /* __VALGRIND_H */