1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/Frameworks/libpurple.framework/Versions/0.6.2/Headers/valgrind.h Fri Aug 21 13:25:11 2009 -0700
1.3 @@ -0,0 +1,3924 @@
1.4 +/* -*- c -*-
1.5 + ----------------------------------------------------------------
1.6 +
1.7 + Notice that the following BSD-style license applies to this one
1.8 + file (valgrind.h) only. The rest of Valgrind is licensed under the
1.9 + terms of the GNU General Public License, version 2, unless
1.10 + otherwise indicated. See the COPYING file in the source
1.11 + distribution for details.
1.12 +
1.13 + ----------------------------------------------------------------
1.14 +
1.15 + This file is part of Valgrind, a dynamic binary instrumentation
1.16 + framework.
1.17 +
1.18 + Copyright (C) 2000-2008 Julian Seward. All rights reserved.
1.19 +
1.20 + Redistribution and use in source and binary forms, with or without
1.21 + modification, are permitted provided that the following conditions
1.22 + are met:
1.23 +
1.24 + 1. Redistributions of source code must retain the above copyright
1.25 + notice, this list of conditions and the following disclaimer.
1.26 +
1.27 + 2. The origin of this software must not be misrepresented; you must
1.28 + not claim that you wrote the original software. If you use this
1.29 + software in a product, an acknowledgment in the product
1.30 + documentation would be appreciated but is not required.
1.31 +
1.32 + 3. Altered source versions must be plainly marked as such, and must
1.33 + not be misrepresented as being the original software.
1.34 +
1.35 + 4. The name of the author may not be used to endorse or promote
1.36 + products derived from this software without specific prior written
1.37 + permission.
1.38 +
1.39 + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
1.40 + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1.41 + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1.42 + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
1.43 + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1.44 + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
1.45 + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1.46 + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
1.47 + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
1.48 + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1.49 + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.50 +
1.51 + ----------------------------------------------------------------
1.52 +
1.53 + Notice that the above BSD-style license applies to this one file
1.54 + (valgrind.h) only. The entire rest of Valgrind is licensed under
1.55 + the terms of the GNU General Public License, version 2. See the
1.56 + COPYING file in the source distribution for details.
1.57 +
1.58 + ----------------------------------------------------------------
1.59 +*/
1.60 +
1.61 +
1.62 +/* This file is for inclusion into client (your!) code.
1.63 +
1.64 + You can use these macros to manipulate and query Valgrind's
1.65 + execution inside your own programs.
1.66 +
1.67 + The resulting executables will still run without Valgrind, just a
1.68 + little bit more slowly than they otherwise would, but otherwise
1.69 + unchanged. When not running on valgrind, each client request
1.70 + consumes very few (eg. 7) instructions, so the resulting performance
1.71 + loss is negligible unless you plan to execute client requests
1.72 + millions of times per second. Nevertheless, if that is still a
1.73 + problem, you can compile with the NVALGRIND symbol defined (gcc
1.74 + -DNVALGRIND) so that client requests are not even compiled in. */
1.75 +
1.76 +#ifndef __VALGRIND_H
1.77 +#define __VALGRIND_H
1.78 +
1.79 +#include <stdarg.h>
1.80 +
1.81 +/* Nb: this file might be included in a file compiled with -ansi. So
1.82 + we can't use C++ style "//" comments nor the "asm" keyword (instead
1.83 + use "__asm__"). */
1.84 +
1.85 +/* Derive some tags indicating what the target platform is. Note
1.86 + that in this file we're using the compiler's CPP symbols for
1.87 + identifying architectures, which are different to the ones we use
1.88 + within the rest of Valgrind. Note, __powerpc__ is active for both
1.89 + 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
1.90 + latter (on Linux, that is). */
1.91 +#undef PLAT_x86_linux
1.92 +#undef PLAT_amd64_linux
1.93 +#undef PLAT_ppc32_linux
1.94 +#undef PLAT_ppc64_linux
1.95 +#undef PLAT_ppc32_aix5
1.96 +#undef PLAT_ppc64_aix5
1.97 +
1.98 +#if !defined(_AIX) && defined(__i386__)
1.99 +# define PLAT_x86_linux 1
1.100 +#elif !defined(_AIX) && defined(__x86_64__)
1.101 +# define PLAT_amd64_linux 1
1.102 +#elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__)
1.103 +# define PLAT_ppc32_linux 1
1.104 +#elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__)
1.105 +# define PLAT_ppc64_linux 1
1.106 +#elif defined(_AIX) && defined(__64BIT__)
1.107 +# define PLAT_ppc64_aix5 1
1.108 +#elif defined(_AIX) && !defined(__64BIT__)
1.109 +# define PLAT_ppc32_aix5 1
1.110 +#endif
1.111 +
1.112 +
1.113 +/* If we're not compiling for our target platform, don't generate
1.114 + any inline asms. */
1.115 +#if !defined(PLAT_x86_linux) && !defined(PLAT_amd64_linux) \
1.116 + && !defined(PLAT_ppc32_linux) && !defined(PLAT_ppc64_linux) \
1.117 + && !defined(PLAT_ppc32_aix5) && !defined(PLAT_ppc64_aix5)
1.118 +# if !defined(NVALGRIND)
1.119 +# define NVALGRIND 1
1.120 +# endif
1.121 +#endif
1.122 +
1.123 +
1.124 +/* ------------------------------------------------------------------ */
1.125 +/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
1.126 +/* in here of use to end-users -- skip to the next section. */
1.127 +/* ------------------------------------------------------------------ */
1.128 +
1.129 +#if defined(NVALGRIND)
1.130 +
1.131 +/* Define NVALGRIND to completely remove the Valgrind magic sequence
1.132 + from the compiled code (analogous to NDEBUG's effects on
1.133 + assert()) */
1.134 +#define VALGRIND_DO_CLIENT_REQUEST( \
1.135 + _zzq_rlval, _zzq_default, _zzq_request, \
1.136 + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
1.137 + { \
1.138 + (_zzq_rlval) = (_zzq_default); \
1.139 + }
1.140 +
1.141 +#else /* ! NVALGRIND */
1.142 +
1.143 +/* The following defines the magic code sequences which the JITter
1.144 + spots and handles magically. Don't look too closely at them as
1.145 + they will rot your brain.
1.146 +
1.147 + The assembly code sequences for all architectures is in this one
1.148 + file. This is because this file must be stand-alone, and we don't
1.149 + want to have multiple files.
1.150 +
1.151 + For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
1.152 + value gets put in the return slot, so that everything works when
1.153 + this is executed not under Valgrind. Args are passed in a memory
1.154 + block, and so there's no intrinsic limit to the number that could
1.155 + be passed, but it's currently five.
1.156 +
1.157 + The macro args are:
1.158 + _zzq_rlval result lvalue
1.159 + _zzq_default default value (result returned when running on real CPU)
1.160 + _zzq_request request code
1.161 + _zzq_arg1..5 request params
1.162 +
1.163 + The other two macros are used to support function wrapping, and are
1.164 + a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
1.165 + guest's NRADDR pseudo-register and whatever other information is
1.166 + needed to safely run the call original from the wrapper: on
1.167 + ppc64-linux, the R2 value at the divert point is also needed. This
1.168 + information is abstracted into a user-visible type, OrigFn.
1.169 +
1.170 + VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
1.171 + guest, but guarantees that the branch instruction will not be
1.172 + redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
1.173 + branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
1.174 + complete inline asm, since it needs to be combined with more magic
1.175 + inline asm stuff to be useful.
1.176 +*/
1.177 +
1.178 +/* ------------------------- x86-linux ------------------------- */
1.179 +
1.180 +#if defined(PLAT_x86_linux)
1.181 +
1.182 +typedef
1.183 + struct {
1.184 + unsigned int nraddr; /* where's the code? */
1.185 + }
1.186 + OrigFn;
1.187 +
1.188 +#define __SPECIAL_INSTRUCTION_PREAMBLE \
1.189 + "roll $3, %%edi ; roll $13, %%edi\n\t" \
1.190 + "roll $29, %%edi ; roll $19, %%edi\n\t"
1.191 +
1.192 +#define VALGRIND_DO_CLIENT_REQUEST( \
1.193 + _zzq_rlval, _zzq_default, _zzq_request, \
1.194 + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
1.195 + { volatile unsigned int _zzq_args[6]; \
1.196 + volatile unsigned int _zzq_result; \
1.197 + _zzq_args[0] = (unsigned int)(_zzq_request); \
1.198 + _zzq_args[1] = (unsigned int)(_zzq_arg1); \
1.199 + _zzq_args[2] = (unsigned int)(_zzq_arg2); \
1.200 + _zzq_args[3] = (unsigned int)(_zzq_arg3); \
1.201 + _zzq_args[4] = (unsigned int)(_zzq_arg4); \
1.202 + _zzq_args[5] = (unsigned int)(_zzq_arg5); \
1.203 + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1.204 + /* %EDX = client_request ( %EAX ) */ \
1.205 + "xchgl %%ebx,%%ebx" \
1.206 + : "=d" (_zzq_result) \
1.207 + : "a" (&_zzq_args[0]), "0" (_zzq_default) \
1.208 + : "cc", "memory" \
1.209 + ); \
1.210 + _zzq_rlval = _zzq_result; \
1.211 + }
1.212 +
1.213 +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
1.214 + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
1.215 + volatile unsigned int __addr; \
1.216 + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1.217 + /* %EAX = guest_NRADDR */ \
1.218 + "xchgl %%ecx,%%ecx" \
1.219 + : "=a" (__addr) \
1.220 + : \
1.221 + : "cc", "memory" \
1.222 + ); \
1.223 + _zzq_orig->nraddr = __addr; \
1.224 + }
1.225 +
1.226 +#define VALGRIND_CALL_NOREDIR_EAX \
1.227 + __SPECIAL_INSTRUCTION_PREAMBLE \
1.228 + /* call-noredir *%EAX */ \
1.229 + "xchgl %%edx,%%edx\n\t"
1.230 +#endif /* PLAT_x86_linux */
1.231 +
1.232 +/* ------------------------ amd64-linux ------------------------ */
1.233 +
1.234 +#if defined(PLAT_amd64_linux)
1.235 +
1.236 +typedef
1.237 + struct {
1.238 + unsigned long long int nraddr; /* where's the code? */
1.239 + }
1.240 + OrigFn;
1.241 +
1.242 +#define __SPECIAL_INSTRUCTION_PREAMBLE \
1.243 + "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
1.244 + "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
1.245 +
1.246 +#define VALGRIND_DO_CLIENT_REQUEST( \
1.247 + _zzq_rlval, _zzq_default, _zzq_request, \
1.248 + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
1.249 + { volatile unsigned long long int _zzq_args[6]; \
1.250 + volatile unsigned long long int _zzq_result; \
1.251 + _zzq_args[0] = (unsigned long long int)(_zzq_request); \
1.252 + _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
1.253 + _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
1.254 + _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
1.255 + _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
1.256 + _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
1.257 + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1.258 + /* %RDX = client_request ( %RAX ) */ \
1.259 + "xchgq %%rbx,%%rbx" \
1.260 + : "=d" (_zzq_result) \
1.261 + : "a" (&_zzq_args[0]), "0" (_zzq_default) \
1.262 + : "cc", "memory" \
1.263 + ); \
1.264 + _zzq_rlval = _zzq_result; \
1.265 + }
1.266 +
1.267 +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
1.268 + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
1.269 + volatile unsigned long long int __addr; \
1.270 + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1.271 + /* %RAX = guest_NRADDR */ \
1.272 + "xchgq %%rcx,%%rcx" \
1.273 + : "=a" (__addr) \
1.274 + : \
1.275 + : "cc", "memory" \
1.276 + ); \
1.277 + _zzq_orig->nraddr = __addr; \
1.278 + }
1.279 +
1.280 +#define VALGRIND_CALL_NOREDIR_RAX \
1.281 + __SPECIAL_INSTRUCTION_PREAMBLE \
1.282 + /* call-noredir *%RAX */ \
1.283 + "xchgq %%rdx,%%rdx\n\t"
1.284 +#endif /* PLAT_amd64_linux */
1.285 +
1.286 +/* ------------------------ ppc32-linux ------------------------ */
1.287 +
1.288 +#if defined(PLAT_ppc32_linux)
1.289 +
1.290 +typedef
1.291 + struct {
1.292 + unsigned int nraddr; /* where's the code? */
1.293 + }
1.294 + OrigFn;
1.295 +
1.296 +#define __SPECIAL_INSTRUCTION_PREAMBLE \
1.297 + "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
1.298 + "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
1.299 +
1.300 +#define VALGRIND_DO_CLIENT_REQUEST( \
1.301 + _zzq_rlval, _zzq_default, _zzq_request, \
1.302 + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
1.303 + \
1.304 + { unsigned int _zzq_args[6]; \
1.305 + unsigned int _zzq_result; \
1.306 + unsigned int* _zzq_ptr; \
1.307 + _zzq_args[0] = (unsigned int)(_zzq_request); \
1.308 + _zzq_args[1] = (unsigned int)(_zzq_arg1); \
1.309 + _zzq_args[2] = (unsigned int)(_zzq_arg2); \
1.310 + _zzq_args[3] = (unsigned int)(_zzq_arg3); \
1.311 + _zzq_args[4] = (unsigned int)(_zzq_arg4); \
1.312 + _zzq_args[5] = (unsigned int)(_zzq_arg5); \
1.313 + _zzq_ptr = _zzq_args; \
1.314 + __asm__ volatile("mr 3,%1\n\t" /*default*/ \
1.315 + "mr 4,%2\n\t" /*ptr*/ \
1.316 + __SPECIAL_INSTRUCTION_PREAMBLE \
1.317 + /* %R3 = client_request ( %R4 ) */ \
1.318 + "or 1,1,1\n\t" \
1.319 + "mr %0,3" /*result*/ \
1.320 + : "=b" (_zzq_result) \
1.321 + : "b" (_zzq_default), "b" (_zzq_ptr) \
1.322 + : "cc", "memory", "r3", "r4"); \
1.323 + _zzq_rlval = _zzq_result; \
1.324 + }
1.325 +
1.326 +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
1.327 + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
1.328 + unsigned int __addr; \
1.329 + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1.330 + /* %R3 = guest_NRADDR */ \
1.331 + "or 2,2,2\n\t" \
1.332 + "mr %0,3" \
1.333 + : "=b" (__addr) \
1.334 + : \
1.335 + : "cc", "memory", "r3" \
1.336 + ); \
1.337 + _zzq_orig->nraddr = __addr; \
1.338 + }
1.339 +
1.340 +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.341 + __SPECIAL_INSTRUCTION_PREAMBLE \
1.342 + /* branch-and-link-to-noredir *%R11 */ \
1.343 + "or 3,3,3\n\t"
1.344 +#endif /* PLAT_ppc32_linux */
1.345 +
1.346 +/* ------------------------ ppc64-linux ------------------------ */
1.347 +
1.348 +#if defined(PLAT_ppc64_linux)
1.349 +
1.350 +typedef
1.351 + struct {
1.352 + unsigned long long int nraddr; /* where's the code? */
1.353 + unsigned long long int r2; /* what tocptr do we need? */
1.354 + }
1.355 + OrigFn;
1.356 +
1.357 +#define __SPECIAL_INSTRUCTION_PREAMBLE \
1.358 + "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
1.359 + "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
1.360 +
1.361 +#define VALGRIND_DO_CLIENT_REQUEST( \
1.362 + _zzq_rlval, _zzq_default, _zzq_request, \
1.363 + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
1.364 + \
1.365 + { unsigned long long int _zzq_args[6]; \
1.366 + register unsigned long long int _zzq_result __asm__("r3"); \
1.367 + register unsigned long long int* _zzq_ptr __asm__("r4"); \
1.368 + _zzq_args[0] = (unsigned long long int)(_zzq_request); \
1.369 + _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
1.370 + _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
1.371 + _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
1.372 + _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
1.373 + _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
1.374 + _zzq_ptr = _zzq_args; \
1.375 + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1.376 + /* %R3 = client_request ( %R4 ) */ \
1.377 + "or 1,1,1" \
1.378 + : "=r" (_zzq_result) \
1.379 + : "0" (_zzq_default), "r" (_zzq_ptr) \
1.380 + : "cc", "memory"); \
1.381 + _zzq_rlval = _zzq_result; \
1.382 + }
1.383 +
1.384 +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
1.385 + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
1.386 + register unsigned long long int __addr __asm__("r3"); \
1.387 + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1.388 + /* %R3 = guest_NRADDR */ \
1.389 + "or 2,2,2" \
1.390 + : "=r" (__addr) \
1.391 + : \
1.392 + : "cc", "memory" \
1.393 + ); \
1.394 + _zzq_orig->nraddr = __addr; \
1.395 + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1.396 + /* %R3 = guest_NRADDR_GPR2 */ \
1.397 + "or 4,4,4" \
1.398 + : "=r" (__addr) \
1.399 + : \
1.400 + : "cc", "memory" \
1.401 + ); \
1.402 + _zzq_orig->r2 = __addr; \
1.403 + }
1.404 +
1.405 +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.406 + __SPECIAL_INSTRUCTION_PREAMBLE \
1.407 + /* branch-and-link-to-noredir *%R11 */ \
1.408 + "or 3,3,3\n\t"
1.409 +
1.410 +#endif /* PLAT_ppc64_linux */
1.411 +
1.412 +/* ------------------------ ppc32-aix5 ------------------------- */
1.413 +
1.414 +#if defined(PLAT_ppc32_aix5)
1.415 +
1.416 +typedef
1.417 + struct {
1.418 + unsigned int nraddr; /* where's the code? */
1.419 + unsigned int r2; /* what tocptr do we need? */
1.420 + }
1.421 + OrigFn;
1.422 +
1.423 +#define __SPECIAL_INSTRUCTION_PREAMBLE \
1.424 + "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
1.425 + "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
1.426 +
1.427 +#define VALGRIND_DO_CLIENT_REQUEST( \
1.428 + _zzq_rlval, _zzq_default, _zzq_request, \
1.429 + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
1.430 + \
1.431 + { unsigned int _zzq_args[7]; \
1.432 + register unsigned int _zzq_result; \
1.433 + register unsigned int* _zzq_ptr; \
1.434 + _zzq_args[0] = (unsigned int)(_zzq_request); \
1.435 + _zzq_args[1] = (unsigned int)(_zzq_arg1); \
1.436 + _zzq_args[2] = (unsigned int)(_zzq_arg2); \
1.437 + _zzq_args[3] = (unsigned int)(_zzq_arg3); \
1.438 + _zzq_args[4] = (unsigned int)(_zzq_arg4); \
1.439 + _zzq_args[5] = (unsigned int)(_zzq_arg5); \
1.440 + _zzq_args[6] = (unsigned int)(_zzq_default); \
1.441 + _zzq_ptr = _zzq_args; \
1.442 + __asm__ volatile("mr 4,%1\n\t" \
1.443 + "lwz 3, 24(4)\n\t" \
1.444 + __SPECIAL_INSTRUCTION_PREAMBLE \
1.445 + /* %R3 = client_request ( %R4 ) */ \
1.446 + "or 1,1,1\n\t" \
1.447 + "mr %0,3" \
1.448 + : "=b" (_zzq_result) \
1.449 + : "b" (_zzq_ptr) \
1.450 + : "r3", "r4", "cc", "memory"); \
1.451 + _zzq_rlval = _zzq_result; \
1.452 + }
1.453 +
1.454 +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
1.455 + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
1.456 + register unsigned int __addr; \
1.457 + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1.458 + /* %R3 = guest_NRADDR */ \
1.459 + "or 2,2,2\n\t" \
1.460 + "mr %0,3" \
1.461 + : "=b" (__addr) \
1.462 + : \
1.463 + : "r3", "cc", "memory" \
1.464 + ); \
1.465 + _zzq_orig->nraddr = __addr; \
1.466 + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1.467 + /* %R3 = guest_NRADDR_GPR2 */ \
1.468 + "or 4,4,4\n\t" \
1.469 + "mr %0,3" \
1.470 + : "=b" (__addr) \
1.471 + : \
1.472 + : "r3", "cc", "memory" \
1.473 + ); \
1.474 + _zzq_orig->r2 = __addr; \
1.475 + }
1.476 +
1.477 +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.478 + __SPECIAL_INSTRUCTION_PREAMBLE \
1.479 + /* branch-and-link-to-noredir *%R11 */ \
1.480 + "or 3,3,3\n\t"
1.481 +
1.482 +#endif /* PLAT_ppc32_aix5 */
1.483 +
1.484 +/* ------------------------ ppc64-aix5 ------------------------- */
1.485 +
1.486 +#if defined(PLAT_ppc64_aix5)
1.487 +
1.488 +typedef
1.489 + struct {
1.490 + unsigned long long int nraddr; /* where's the code? */
1.491 + unsigned long long int r2; /* what tocptr do we need? */
1.492 + }
1.493 + OrigFn;
1.494 +
1.495 +#define __SPECIAL_INSTRUCTION_PREAMBLE \
1.496 + "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
1.497 + "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
1.498 +
1.499 +#define VALGRIND_DO_CLIENT_REQUEST( \
1.500 + _zzq_rlval, _zzq_default, _zzq_request, \
1.501 + _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
1.502 + \
1.503 + { unsigned long long int _zzq_args[7]; \
1.504 + register unsigned long long int _zzq_result; \
1.505 + register unsigned long long int* _zzq_ptr; \
1.506 + _zzq_args[0] = (unsigned int long long)(_zzq_request); \
1.507 + _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
1.508 + _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
1.509 + _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
1.510 + _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
1.511 + _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
1.512 + _zzq_args[6] = (unsigned int long long)(_zzq_default); \
1.513 + _zzq_ptr = _zzq_args; \
1.514 + __asm__ volatile("mr 4,%1\n\t" \
1.515 + "ld 3, 48(4)\n\t" \
1.516 + __SPECIAL_INSTRUCTION_PREAMBLE \
1.517 + /* %R3 = client_request ( %R4 ) */ \
1.518 + "or 1,1,1\n\t" \
1.519 + "mr %0,3" \
1.520 + : "=b" (_zzq_result) \
1.521 + : "b" (_zzq_ptr) \
1.522 + : "r3", "r4", "cc", "memory"); \
1.523 + _zzq_rlval = _zzq_result; \
1.524 + }
1.525 +
1.526 +#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
1.527 + { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
1.528 + register unsigned long long int __addr; \
1.529 + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1.530 + /* %R3 = guest_NRADDR */ \
1.531 + "or 2,2,2\n\t" \
1.532 + "mr %0,3" \
1.533 + : "=b" (__addr) \
1.534 + : \
1.535 + : "r3", "cc", "memory" \
1.536 + ); \
1.537 + _zzq_orig->nraddr = __addr; \
1.538 + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
1.539 + /* %R3 = guest_NRADDR_GPR2 */ \
1.540 + "or 4,4,4\n\t" \
1.541 + "mr %0,3" \
1.542 + : "=b" (__addr) \
1.543 + : \
1.544 + : "r3", "cc", "memory" \
1.545 + ); \
1.546 + _zzq_orig->r2 = __addr; \
1.547 + }
1.548 +
1.549 +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.550 + __SPECIAL_INSTRUCTION_PREAMBLE \
1.551 + /* branch-and-link-to-noredir *%R11 */ \
1.552 + "or 3,3,3\n\t"
1.553 +
1.554 +#endif /* PLAT_ppc64_aix5 */
1.555 +
1.556 +/* Insert assembly code for other platforms here... */
1.557 +
1.558 +#endif /* NVALGRIND */
1.559 +
1.560 +
1.561 +/* ------------------------------------------------------------------ */
1.562 +/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
1.563 +/* ugly. It's the least-worst tradeoff I can think of. */
1.564 +/* ------------------------------------------------------------------ */
1.565 +
1.566 +/* This section defines magic (a.k.a appalling-hack) macros for doing
1.567 + guaranteed-no-redirection macros, so as to get from function
1.568 + wrappers to the functions they are wrapping. The whole point is to
1.569 + construct standard call sequences, but to do the call itself with a
1.570 + special no-redirect call pseudo-instruction that the JIT
1.571 + understands and handles specially. This section is long and
1.572 + repetitious, and I can't see a way to make it shorter.
1.573 +
1.574 + The naming scheme is as follows:
1.575 +
1.576 + CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
1.577 +
1.578 + 'W' stands for "word" and 'v' for "void". Hence there are
1.579 + different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
1.580 + and for each, the possibility of returning a word-typed result, or
1.581 + no result.
1.582 +*/
1.583 +
1.584 +/* Use these to write the name of your wrapper. NOTE: duplicates
1.585 + VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
1.586 +
1.587 +#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
1.588 + _vgwZU_##soname##_##fnname
1.589 +
1.590 +#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
1.591 + _vgwZZ_##soname##_##fnname
1.592 +
1.593 +/* Use this macro from within a wrapper function to collect the
1.594 + context (address and possibly other info) of the original function.
1.595 + Once you have that you can then use it in one of the CALL_FN_
1.596 + macros. The type of the argument _lval is OrigFn. */
1.597 +#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
1.598 +
1.599 +/* Derivatives of the main macros below, for calling functions
1.600 + returning void. */
1.601 +
1.602 +#define CALL_FN_v_v(fnptr) \
1.603 + do { volatile unsigned long _junk; \
1.604 + CALL_FN_W_v(_junk,fnptr); } while (0)
1.605 +
1.606 +#define CALL_FN_v_W(fnptr, arg1) \
1.607 + do { volatile unsigned long _junk; \
1.608 + CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
1.609 +
1.610 +#define CALL_FN_v_WW(fnptr, arg1,arg2) \
1.611 + do { volatile unsigned long _junk; \
1.612 + CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
1.613 +
1.614 +#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
1.615 + do { volatile unsigned long _junk; \
1.616 + CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
1.617 +
1.618 +/* ------------------------- x86-linux ------------------------- */
1.619 +
1.620 +#if defined(PLAT_x86_linux)
1.621 +
1.622 +/* These regs are trashed by the hidden call. No need to mention eax
1.623 + as gcc can already see that, plus causes gcc to bomb. */
1.624 +#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
1.625 +
1.626 +/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
1.627 + long) == 4. */
1.628 +
1.629 +#define CALL_FN_W_v(lval, orig) \
1.630 + do { \
1.631 + volatile OrigFn _orig = (orig); \
1.632 + volatile unsigned long _argvec[1]; \
1.633 + volatile unsigned long _res; \
1.634 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.635 + __asm__ volatile( \
1.636 + "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1.637 + VALGRIND_CALL_NOREDIR_EAX \
1.638 + : /*out*/ "=a" (_res) \
1.639 + : /*in*/ "a" (&_argvec[0]) \
1.640 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.641 + ); \
1.642 + lval = (__typeof__(lval)) _res; \
1.643 + } while (0)
1.644 +
1.645 +#define CALL_FN_W_W(lval, orig, arg1) \
1.646 + do { \
1.647 + volatile OrigFn _orig = (orig); \
1.648 + volatile unsigned long _argvec[2]; \
1.649 + volatile unsigned long _res; \
1.650 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.651 + _argvec[1] = (unsigned long)(arg1); \
1.652 + __asm__ volatile( \
1.653 + "pushl 4(%%eax)\n\t" \
1.654 + "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1.655 + VALGRIND_CALL_NOREDIR_EAX \
1.656 + "addl $4, %%esp\n" \
1.657 + : /*out*/ "=a" (_res) \
1.658 + : /*in*/ "a" (&_argvec[0]) \
1.659 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.660 + ); \
1.661 + lval = (__typeof__(lval)) _res; \
1.662 + } while (0)
1.663 +
1.664 +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1.665 + do { \
1.666 + volatile OrigFn _orig = (orig); \
1.667 + volatile unsigned long _argvec[3]; \
1.668 + volatile unsigned long _res; \
1.669 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.670 + _argvec[1] = (unsigned long)(arg1); \
1.671 + _argvec[2] = (unsigned long)(arg2); \
1.672 + __asm__ volatile( \
1.673 + "pushl 8(%%eax)\n\t" \
1.674 + "pushl 4(%%eax)\n\t" \
1.675 + "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1.676 + VALGRIND_CALL_NOREDIR_EAX \
1.677 + "addl $8, %%esp\n" \
1.678 + : /*out*/ "=a" (_res) \
1.679 + : /*in*/ "a" (&_argvec[0]) \
1.680 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.681 + ); \
1.682 + lval = (__typeof__(lval)) _res; \
1.683 + } while (0)
1.684 +
1.685 +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1.686 + do { \
1.687 + volatile OrigFn _orig = (orig); \
1.688 + volatile unsigned long _argvec[4]; \
1.689 + volatile unsigned long _res; \
1.690 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.691 + _argvec[1] = (unsigned long)(arg1); \
1.692 + _argvec[2] = (unsigned long)(arg2); \
1.693 + _argvec[3] = (unsigned long)(arg3); \
1.694 + __asm__ volatile( \
1.695 + "pushl 12(%%eax)\n\t" \
1.696 + "pushl 8(%%eax)\n\t" \
1.697 + "pushl 4(%%eax)\n\t" \
1.698 + "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1.699 + VALGRIND_CALL_NOREDIR_EAX \
1.700 + "addl $12, %%esp\n" \
1.701 + : /*out*/ "=a" (_res) \
1.702 + : /*in*/ "a" (&_argvec[0]) \
1.703 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.704 + ); \
1.705 + lval = (__typeof__(lval)) _res; \
1.706 + } while (0)
1.707 +
1.708 +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1.709 + do { \
1.710 + volatile OrigFn _orig = (orig); \
1.711 + volatile unsigned long _argvec[5]; \
1.712 + volatile unsigned long _res; \
1.713 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.714 + _argvec[1] = (unsigned long)(arg1); \
1.715 + _argvec[2] = (unsigned long)(arg2); \
1.716 + _argvec[3] = (unsigned long)(arg3); \
1.717 + _argvec[4] = (unsigned long)(arg4); \
1.718 + __asm__ volatile( \
1.719 + "pushl 16(%%eax)\n\t" \
1.720 + "pushl 12(%%eax)\n\t" \
1.721 + "pushl 8(%%eax)\n\t" \
1.722 + "pushl 4(%%eax)\n\t" \
1.723 + "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1.724 + VALGRIND_CALL_NOREDIR_EAX \
1.725 + "addl $16, %%esp\n" \
1.726 + : /*out*/ "=a" (_res) \
1.727 + : /*in*/ "a" (&_argvec[0]) \
1.728 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.729 + ); \
1.730 + lval = (__typeof__(lval)) _res; \
1.731 + } while (0)
1.732 +
1.733 +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1.734 + do { \
1.735 + volatile OrigFn _orig = (orig); \
1.736 + volatile unsigned long _argvec[6]; \
1.737 + volatile unsigned long _res; \
1.738 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.739 + _argvec[1] = (unsigned long)(arg1); \
1.740 + _argvec[2] = (unsigned long)(arg2); \
1.741 + _argvec[3] = (unsigned long)(arg3); \
1.742 + _argvec[4] = (unsigned long)(arg4); \
1.743 + _argvec[5] = (unsigned long)(arg5); \
1.744 + __asm__ volatile( \
1.745 + "pushl 20(%%eax)\n\t" \
1.746 + "pushl 16(%%eax)\n\t" \
1.747 + "pushl 12(%%eax)\n\t" \
1.748 + "pushl 8(%%eax)\n\t" \
1.749 + "pushl 4(%%eax)\n\t" \
1.750 + "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1.751 + VALGRIND_CALL_NOREDIR_EAX \
1.752 + "addl $20, %%esp\n" \
1.753 + : /*out*/ "=a" (_res) \
1.754 + : /*in*/ "a" (&_argvec[0]) \
1.755 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.756 + ); \
1.757 + lval = (__typeof__(lval)) _res; \
1.758 + } while (0)
1.759 +
1.760 +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1.761 + do { \
1.762 + volatile OrigFn _orig = (orig); \
1.763 + volatile unsigned long _argvec[7]; \
1.764 + volatile unsigned long _res; \
1.765 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.766 + _argvec[1] = (unsigned long)(arg1); \
1.767 + _argvec[2] = (unsigned long)(arg2); \
1.768 + _argvec[3] = (unsigned long)(arg3); \
1.769 + _argvec[4] = (unsigned long)(arg4); \
1.770 + _argvec[5] = (unsigned long)(arg5); \
1.771 + _argvec[6] = (unsigned long)(arg6); \
1.772 + __asm__ volatile( \
1.773 + "pushl 24(%%eax)\n\t" \
1.774 + "pushl 20(%%eax)\n\t" \
1.775 + "pushl 16(%%eax)\n\t" \
1.776 + "pushl 12(%%eax)\n\t" \
1.777 + "pushl 8(%%eax)\n\t" \
1.778 + "pushl 4(%%eax)\n\t" \
1.779 + "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1.780 + VALGRIND_CALL_NOREDIR_EAX \
1.781 + "addl $24, %%esp\n" \
1.782 + : /*out*/ "=a" (_res) \
1.783 + : /*in*/ "a" (&_argvec[0]) \
1.784 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.785 + ); \
1.786 + lval = (__typeof__(lval)) _res; \
1.787 + } while (0)
1.788 +
1.789 +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.790 + arg7) \
1.791 + do { \
1.792 + volatile OrigFn _orig = (orig); \
1.793 + volatile unsigned long _argvec[8]; \
1.794 + volatile unsigned long _res; \
1.795 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.796 + _argvec[1] = (unsigned long)(arg1); \
1.797 + _argvec[2] = (unsigned long)(arg2); \
1.798 + _argvec[3] = (unsigned long)(arg3); \
1.799 + _argvec[4] = (unsigned long)(arg4); \
1.800 + _argvec[5] = (unsigned long)(arg5); \
1.801 + _argvec[6] = (unsigned long)(arg6); \
1.802 + _argvec[7] = (unsigned long)(arg7); \
1.803 + __asm__ volatile( \
1.804 + "pushl 28(%%eax)\n\t" \
1.805 + "pushl 24(%%eax)\n\t" \
1.806 + "pushl 20(%%eax)\n\t" \
1.807 + "pushl 16(%%eax)\n\t" \
1.808 + "pushl 12(%%eax)\n\t" \
1.809 + "pushl 8(%%eax)\n\t" \
1.810 + "pushl 4(%%eax)\n\t" \
1.811 + "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1.812 + VALGRIND_CALL_NOREDIR_EAX \
1.813 + "addl $28, %%esp\n" \
1.814 + : /*out*/ "=a" (_res) \
1.815 + : /*in*/ "a" (&_argvec[0]) \
1.816 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.817 + ); \
1.818 + lval = (__typeof__(lval)) _res; \
1.819 + } while (0)
1.820 +
1.821 +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.822 + arg7,arg8) \
1.823 + do { \
1.824 + volatile OrigFn _orig = (orig); \
1.825 + volatile unsigned long _argvec[9]; \
1.826 + volatile unsigned long _res; \
1.827 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.828 + _argvec[1] = (unsigned long)(arg1); \
1.829 + _argvec[2] = (unsigned long)(arg2); \
1.830 + _argvec[3] = (unsigned long)(arg3); \
1.831 + _argvec[4] = (unsigned long)(arg4); \
1.832 + _argvec[5] = (unsigned long)(arg5); \
1.833 + _argvec[6] = (unsigned long)(arg6); \
1.834 + _argvec[7] = (unsigned long)(arg7); \
1.835 + _argvec[8] = (unsigned long)(arg8); \
1.836 + __asm__ volatile( \
1.837 + "pushl 32(%%eax)\n\t" \
1.838 + "pushl 28(%%eax)\n\t" \
1.839 + "pushl 24(%%eax)\n\t" \
1.840 + "pushl 20(%%eax)\n\t" \
1.841 + "pushl 16(%%eax)\n\t" \
1.842 + "pushl 12(%%eax)\n\t" \
1.843 + "pushl 8(%%eax)\n\t" \
1.844 + "pushl 4(%%eax)\n\t" \
1.845 + "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1.846 + VALGRIND_CALL_NOREDIR_EAX \
1.847 + "addl $32, %%esp\n" \
1.848 + : /*out*/ "=a" (_res) \
1.849 + : /*in*/ "a" (&_argvec[0]) \
1.850 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.851 + ); \
1.852 + lval = (__typeof__(lval)) _res; \
1.853 + } while (0)
1.854 +
1.855 +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.856 + arg7,arg8,arg9) \
1.857 + do { \
1.858 + volatile OrigFn _orig = (orig); \
1.859 + volatile unsigned long _argvec[10]; \
1.860 + volatile unsigned long _res; \
1.861 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.862 + _argvec[1] = (unsigned long)(arg1); \
1.863 + _argvec[2] = (unsigned long)(arg2); \
1.864 + _argvec[3] = (unsigned long)(arg3); \
1.865 + _argvec[4] = (unsigned long)(arg4); \
1.866 + _argvec[5] = (unsigned long)(arg5); \
1.867 + _argvec[6] = (unsigned long)(arg6); \
1.868 + _argvec[7] = (unsigned long)(arg7); \
1.869 + _argvec[8] = (unsigned long)(arg8); \
1.870 + _argvec[9] = (unsigned long)(arg9); \
1.871 + __asm__ volatile( \
1.872 + "pushl 36(%%eax)\n\t" \
1.873 + "pushl 32(%%eax)\n\t" \
1.874 + "pushl 28(%%eax)\n\t" \
1.875 + "pushl 24(%%eax)\n\t" \
1.876 + "pushl 20(%%eax)\n\t" \
1.877 + "pushl 16(%%eax)\n\t" \
1.878 + "pushl 12(%%eax)\n\t" \
1.879 + "pushl 8(%%eax)\n\t" \
1.880 + "pushl 4(%%eax)\n\t" \
1.881 + "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1.882 + VALGRIND_CALL_NOREDIR_EAX \
1.883 + "addl $36, %%esp\n" \
1.884 + : /*out*/ "=a" (_res) \
1.885 + : /*in*/ "a" (&_argvec[0]) \
1.886 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.887 + ); \
1.888 + lval = (__typeof__(lval)) _res; \
1.889 + } while (0)
1.890 +
1.891 +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.892 + arg7,arg8,arg9,arg10) \
1.893 + do { \
1.894 + volatile OrigFn _orig = (orig); \
1.895 + volatile unsigned long _argvec[11]; \
1.896 + volatile unsigned long _res; \
1.897 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.898 + _argvec[1] = (unsigned long)(arg1); \
1.899 + _argvec[2] = (unsigned long)(arg2); \
1.900 + _argvec[3] = (unsigned long)(arg3); \
1.901 + _argvec[4] = (unsigned long)(arg4); \
1.902 + _argvec[5] = (unsigned long)(arg5); \
1.903 + _argvec[6] = (unsigned long)(arg6); \
1.904 + _argvec[7] = (unsigned long)(arg7); \
1.905 + _argvec[8] = (unsigned long)(arg8); \
1.906 + _argvec[9] = (unsigned long)(arg9); \
1.907 + _argvec[10] = (unsigned long)(arg10); \
1.908 + __asm__ volatile( \
1.909 + "pushl 40(%%eax)\n\t" \
1.910 + "pushl 36(%%eax)\n\t" \
1.911 + "pushl 32(%%eax)\n\t" \
1.912 + "pushl 28(%%eax)\n\t" \
1.913 + "pushl 24(%%eax)\n\t" \
1.914 + "pushl 20(%%eax)\n\t" \
1.915 + "pushl 16(%%eax)\n\t" \
1.916 + "pushl 12(%%eax)\n\t" \
1.917 + "pushl 8(%%eax)\n\t" \
1.918 + "pushl 4(%%eax)\n\t" \
1.919 + "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1.920 + VALGRIND_CALL_NOREDIR_EAX \
1.921 + "addl $40, %%esp\n" \
1.922 + : /*out*/ "=a" (_res) \
1.923 + : /*in*/ "a" (&_argvec[0]) \
1.924 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.925 + ); \
1.926 + lval = (__typeof__(lval)) _res; \
1.927 + } while (0)
1.928 +
1.929 +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1.930 + arg6,arg7,arg8,arg9,arg10, \
1.931 + arg11) \
1.932 + do { \
1.933 + volatile OrigFn _orig = (orig); \
1.934 + volatile unsigned long _argvec[12]; \
1.935 + volatile unsigned long _res; \
1.936 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.937 + _argvec[1] = (unsigned long)(arg1); \
1.938 + _argvec[2] = (unsigned long)(arg2); \
1.939 + _argvec[3] = (unsigned long)(arg3); \
1.940 + _argvec[4] = (unsigned long)(arg4); \
1.941 + _argvec[5] = (unsigned long)(arg5); \
1.942 + _argvec[6] = (unsigned long)(arg6); \
1.943 + _argvec[7] = (unsigned long)(arg7); \
1.944 + _argvec[8] = (unsigned long)(arg8); \
1.945 + _argvec[9] = (unsigned long)(arg9); \
1.946 + _argvec[10] = (unsigned long)(arg10); \
1.947 + _argvec[11] = (unsigned long)(arg11); \
1.948 + __asm__ volatile( \
1.949 + "pushl 44(%%eax)\n\t" \
1.950 + "pushl 40(%%eax)\n\t" \
1.951 + "pushl 36(%%eax)\n\t" \
1.952 + "pushl 32(%%eax)\n\t" \
1.953 + "pushl 28(%%eax)\n\t" \
1.954 + "pushl 24(%%eax)\n\t" \
1.955 + "pushl 20(%%eax)\n\t" \
1.956 + "pushl 16(%%eax)\n\t" \
1.957 + "pushl 12(%%eax)\n\t" \
1.958 + "pushl 8(%%eax)\n\t" \
1.959 + "pushl 4(%%eax)\n\t" \
1.960 + "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1.961 + VALGRIND_CALL_NOREDIR_EAX \
1.962 + "addl $44, %%esp\n" \
1.963 + : /*out*/ "=a" (_res) \
1.964 + : /*in*/ "a" (&_argvec[0]) \
1.965 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.966 + ); \
1.967 + lval = (__typeof__(lval)) _res; \
1.968 + } while (0)
1.969 +
1.970 +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
1.971 + arg6,arg7,arg8,arg9,arg10, \
1.972 + arg11,arg12) \
1.973 + do { \
1.974 + volatile OrigFn _orig = (orig); \
1.975 + volatile unsigned long _argvec[13]; \
1.976 + volatile unsigned long _res; \
1.977 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.978 + _argvec[1] = (unsigned long)(arg1); \
1.979 + _argvec[2] = (unsigned long)(arg2); \
1.980 + _argvec[3] = (unsigned long)(arg3); \
1.981 + _argvec[4] = (unsigned long)(arg4); \
1.982 + _argvec[5] = (unsigned long)(arg5); \
1.983 + _argvec[6] = (unsigned long)(arg6); \
1.984 + _argvec[7] = (unsigned long)(arg7); \
1.985 + _argvec[8] = (unsigned long)(arg8); \
1.986 + _argvec[9] = (unsigned long)(arg9); \
1.987 + _argvec[10] = (unsigned long)(arg10); \
1.988 + _argvec[11] = (unsigned long)(arg11); \
1.989 + _argvec[12] = (unsigned long)(arg12); \
1.990 + __asm__ volatile( \
1.991 + "pushl 48(%%eax)\n\t" \
1.992 + "pushl 44(%%eax)\n\t" \
1.993 + "pushl 40(%%eax)\n\t" \
1.994 + "pushl 36(%%eax)\n\t" \
1.995 + "pushl 32(%%eax)\n\t" \
1.996 + "pushl 28(%%eax)\n\t" \
1.997 + "pushl 24(%%eax)\n\t" \
1.998 + "pushl 20(%%eax)\n\t" \
1.999 + "pushl 16(%%eax)\n\t" \
1.1000 + "pushl 12(%%eax)\n\t" \
1.1001 + "pushl 8(%%eax)\n\t" \
1.1002 + "pushl 4(%%eax)\n\t" \
1.1003 + "movl (%%eax), %%eax\n\t" /* target->%eax */ \
1.1004 + VALGRIND_CALL_NOREDIR_EAX \
1.1005 + "addl $48, %%esp\n" \
1.1006 + : /*out*/ "=a" (_res) \
1.1007 + : /*in*/ "a" (&_argvec[0]) \
1.1008 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1009 + ); \
1.1010 + lval = (__typeof__(lval)) _res; \
1.1011 + } while (0)
1.1012 +
1.1013 +#endif /* PLAT_x86_linux */
1.1014 +
1.1015 +/* ------------------------ amd64-linux ------------------------ */
1.1016 +
1.1017 +#if defined(PLAT_amd64_linux)
1.1018 +
1.1019 +/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1.1020 +
1.1021 +/* These regs are trashed by the hidden call. */
1.1022 +#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
1.1023 + "rdi", "r8", "r9", "r10", "r11"
1.1024 +
1.1025 +/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1.1026 + long) == 8. */
1.1027 +
1.1028 +/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
1.1029 + macros. In order not to trash the stack redzone, we need to drop
1.1030 + %rsp by 128 before the hidden call, and restore afterwards. The
1.1031 + nastyness is that it is only by luck that the stack still appears
1.1032 + to be unwindable during the hidden call - since then the behaviour
1.1033 + of any routine using this macro does not match what the CFI data
1.1034 + says. Sigh.
1.1035 +
1.1036 + Why is this important? Imagine that a wrapper has a stack
1.1037 + allocated local, and passes to the hidden call, a pointer to it.
1.1038 + Because gcc does not know about the hidden call, it may allocate
1.1039 + that local in the redzone. Unfortunately the hidden call may then
1.1040 + trash it before it comes to use it. So we must step clear of the
1.1041 + redzone, for the duration of the hidden call, to make it safe.
1.1042 +
1.1043 + Probably the same problem afflicts the other redzone-style ABIs too
1.1044 + (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
1.1045 + self describing (none of this CFI nonsense) so at least messing
1.1046 + with the stack pointer doesn't give a danger of non-unwindable
1.1047 + stack. */
1.1048 +
1.1049 +#define CALL_FN_W_v(lval, orig) \
1.1050 + do { \
1.1051 + volatile OrigFn _orig = (orig); \
1.1052 + volatile unsigned long _argvec[1]; \
1.1053 + volatile unsigned long _res; \
1.1054 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1055 + __asm__ volatile( \
1.1056 + "subq $128,%%rsp\n\t" \
1.1057 + "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1.1058 + VALGRIND_CALL_NOREDIR_RAX \
1.1059 + "addq $128,%%rsp\n\t" \
1.1060 + : /*out*/ "=a" (_res) \
1.1061 + : /*in*/ "a" (&_argvec[0]) \
1.1062 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1063 + ); \
1.1064 + lval = (__typeof__(lval)) _res; \
1.1065 + } while (0)
1.1066 +
1.1067 +#define CALL_FN_W_W(lval, orig, arg1) \
1.1068 + do { \
1.1069 + volatile OrigFn _orig = (orig); \
1.1070 + volatile unsigned long _argvec[2]; \
1.1071 + volatile unsigned long _res; \
1.1072 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1073 + _argvec[1] = (unsigned long)(arg1); \
1.1074 + __asm__ volatile( \
1.1075 + "subq $128,%%rsp\n\t" \
1.1076 + "movq 8(%%rax), %%rdi\n\t" \
1.1077 + "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1.1078 + VALGRIND_CALL_NOREDIR_RAX \
1.1079 + "addq $128,%%rsp\n\t" \
1.1080 + : /*out*/ "=a" (_res) \
1.1081 + : /*in*/ "a" (&_argvec[0]) \
1.1082 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1083 + ); \
1.1084 + lval = (__typeof__(lval)) _res; \
1.1085 + } while (0)
1.1086 +
1.1087 +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1.1088 + do { \
1.1089 + volatile OrigFn _orig = (orig); \
1.1090 + volatile unsigned long _argvec[3]; \
1.1091 + volatile unsigned long _res; \
1.1092 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1093 + _argvec[1] = (unsigned long)(arg1); \
1.1094 + _argvec[2] = (unsigned long)(arg2); \
1.1095 + __asm__ volatile( \
1.1096 + "subq $128,%%rsp\n\t" \
1.1097 + "movq 16(%%rax), %%rsi\n\t" \
1.1098 + "movq 8(%%rax), %%rdi\n\t" \
1.1099 + "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1.1100 + VALGRIND_CALL_NOREDIR_RAX \
1.1101 + "addq $128,%%rsp\n\t" \
1.1102 + : /*out*/ "=a" (_res) \
1.1103 + : /*in*/ "a" (&_argvec[0]) \
1.1104 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1105 + ); \
1.1106 + lval = (__typeof__(lval)) _res; \
1.1107 + } while (0)
1.1108 +
1.1109 +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1.1110 + do { \
1.1111 + volatile OrigFn _orig = (orig); \
1.1112 + volatile unsigned long _argvec[4]; \
1.1113 + volatile unsigned long _res; \
1.1114 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1115 + _argvec[1] = (unsigned long)(arg1); \
1.1116 + _argvec[2] = (unsigned long)(arg2); \
1.1117 + _argvec[3] = (unsigned long)(arg3); \
1.1118 + __asm__ volatile( \
1.1119 + "subq $128,%%rsp\n\t" \
1.1120 + "movq 24(%%rax), %%rdx\n\t" \
1.1121 + "movq 16(%%rax), %%rsi\n\t" \
1.1122 + "movq 8(%%rax), %%rdi\n\t" \
1.1123 + "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1.1124 + VALGRIND_CALL_NOREDIR_RAX \
1.1125 + "addq $128,%%rsp\n\t" \
1.1126 + : /*out*/ "=a" (_res) \
1.1127 + : /*in*/ "a" (&_argvec[0]) \
1.1128 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1129 + ); \
1.1130 + lval = (__typeof__(lval)) _res; \
1.1131 + } while (0)
1.1132 +
1.1133 +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1.1134 + do { \
1.1135 + volatile OrigFn _orig = (orig); \
1.1136 + volatile unsigned long _argvec[5]; \
1.1137 + volatile unsigned long _res; \
1.1138 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1139 + _argvec[1] = (unsigned long)(arg1); \
1.1140 + _argvec[2] = (unsigned long)(arg2); \
1.1141 + _argvec[3] = (unsigned long)(arg3); \
1.1142 + _argvec[4] = (unsigned long)(arg4); \
1.1143 + __asm__ volatile( \
1.1144 + "subq $128,%%rsp\n\t" \
1.1145 + "movq 32(%%rax), %%rcx\n\t" \
1.1146 + "movq 24(%%rax), %%rdx\n\t" \
1.1147 + "movq 16(%%rax), %%rsi\n\t" \
1.1148 + "movq 8(%%rax), %%rdi\n\t" \
1.1149 + "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1.1150 + VALGRIND_CALL_NOREDIR_RAX \
1.1151 + "addq $128,%%rsp\n\t" \
1.1152 + : /*out*/ "=a" (_res) \
1.1153 + : /*in*/ "a" (&_argvec[0]) \
1.1154 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1155 + ); \
1.1156 + lval = (__typeof__(lval)) _res; \
1.1157 + } while (0)
1.1158 +
1.1159 +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1.1160 + do { \
1.1161 + volatile OrigFn _orig = (orig); \
1.1162 + volatile unsigned long _argvec[6]; \
1.1163 + volatile unsigned long _res; \
1.1164 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1165 + _argvec[1] = (unsigned long)(arg1); \
1.1166 + _argvec[2] = (unsigned long)(arg2); \
1.1167 + _argvec[3] = (unsigned long)(arg3); \
1.1168 + _argvec[4] = (unsigned long)(arg4); \
1.1169 + _argvec[5] = (unsigned long)(arg5); \
1.1170 + __asm__ volatile( \
1.1171 + "subq $128,%%rsp\n\t" \
1.1172 + "movq 40(%%rax), %%r8\n\t" \
1.1173 + "movq 32(%%rax), %%rcx\n\t" \
1.1174 + "movq 24(%%rax), %%rdx\n\t" \
1.1175 + "movq 16(%%rax), %%rsi\n\t" \
1.1176 + "movq 8(%%rax), %%rdi\n\t" \
1.1177 + "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1.1178 + VALGRIND_CALL_NOREDIR_RAX \
1.1179 + "addq $128,%%rsp\n\t" \
1.1180 + : /*out*/ "=a" (_res) \
1.1181 + : /*in*/ "a" (&_argvec[0]) \
1.1182 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1183 + ); \
1.1184 + lval = (__typeof__(lval)) _res; \
1.1185 + } while (0)
1.1186 +
1.1187 +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1.1188 + do { \
1.1189 + volatile OrigFn _orig = (orig); \
1.1190 + volatile unsigned long _argvec[7]; \
1.1191 + volatile unsigned long _res; \
1.1192 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1193 + _argvec[1] = (unsigned long)(arg1); \
1.1194 + _argvec[2] = (unsigned long)(arg2); \
1.1195 + _argvec[3] = (unsigned long)(arg3); \
1.1196 + _argvec[4] = (unsigned long)(arg4); \
1.1197 + _argvec[5] = (unsigned long)(arg5); \
1.1198 + _argvec[6] = (unsigned long)(arg6); \
1.1199 + __asm__ volatile( \
1.1200 + "subq $128,%%rsp\n\t" \
1.1201 + "movq 48(%%rax), %%r9\n\t" \
1.1202 + "movq 40(%%rax), %%r8\n\t" \
1.1203 + "movq 32(%%rax), %%rcx\n\t" \
1.1204 + "movq 24(%%rax), %%rdx\n\t" \
1.1205 + "movq 16(%%rax), %%rsi\n\t" \
1.1206 + "movq 8(%%rax), %%rdi\n\t" \
1.1207 + "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1.1208 + "addq $128,%%rsp\n\t" \
1.1209 + VALGRIND_CALL_NOREDIR_RAX \
1.1210 + : /*out*/ "=a" (_res) \
1.1211 + : /*in*/ "a" (&_argvec[0]) \
1.1212 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1213 + ); \
1.1214 + lval = (__typeof__(lval)) _res; \
1.1215 + } while (0)
1.1216 +
1.1217 +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.1218 + arg7) \
1.1219 + do { \
1.1220 + volatile OrigFn _orig = (orig); \
1.1221 + volatile unsigned long _argvec[8]; \
1.1222 + volatile unsigned long _res; \
1.1223 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1224 + _argvec[1] = (unsigned long)(arg1); \
1.1225 + _argvec[2] = (unsigned long)(arg2); \
1.1226 + _argvec[3] = (unsigned long)(arg3); \
1.1227 + _argvec[4] = (unsigned long)(arg4); \
1.1228 + _argvec[5] = (unsigned long)(arg5); \
1.1229 + _argvec[6] = (unsigned long)(arg6); \
1.1230 + _argvec[7] = (unsigned long)(arg7); \
1.1231 + __asm__ volatile( \
1.1232 + "subq $128,%%rsp\n\t" \
1.1233 + "pushq 56(%%rax)\n\t" \
1.1234 + "movq 48(%%rax), %%r9\n\t" \
1.1235 + "movq 40(%%rax), %%r8\n\t" \
1.1236 + "movq 32(%%rax), %%rcx\n\t" \
1.1237 + "movq 24(%%rax), %%rdx\n\t" \
1.1238 + "movq 16(%%rax), %%rsi\n\t" \
1.1239 + "movq 8(%%rax), %%rdi\n\t" \
1.1240 + "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1.1241 + VALGRIND_CALL_NOREDIR_RAX \
1.1242 + "addq $8, %%rsp\n" \
1.1243 + "addq $128,%%rsp\n\t" \
1.1244 + : /*out*/ "=a" (_res) \
1.1245 + : /*in*/ "a" (&_argvec[0]) \
1.1246 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1247 + ); \
1.1248 + lval = (__typeof__(lval)) _res; \
1.1249 + } while (0)
1.1250 +
1.1251 +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.1252 + arg7,arg8) \
1.1253 + do { \
1.1254 + volatile OrigFn _orig = (orig); \
1.1255 + volatile unsigned long _argvec[9]; \
1.1256 + volatile unsigned long _res; \
1.1257 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1258 + _argvec[1] = (unsigned long)(arg1); \
1.1259 + _argvec[2] = (unsigned long)(arg2); \
1.1260 + _argvec[3] = (unsigned long)(arg3); \
1.1261 + _argvec[4] = (unsigned long)(arg4); \
1.1262 + _argvec[5] = (unsigned long)(arg5); \
1.1263 + _argvec[6] = (unsigned long)(arg6); \
1.1264 + _argvec[7] = (unsigned long)(arg7); \
1.1265 + _argvec[8] = (unsigned long)(arg8); \
1.1266 + __asm__ volatile( \
1.1267 + "subq $128,%%rsp\n\t" \
1.1268 + "pushq 64(%%rax)\n\t" \
1.1269 + "pushq 56(%%rax)\n\t" \
1.1270 + "movq 48(%%rax), %%r9\n\t" \
1.1271 + "movq 40(%%rax), %%r8\n\t" \
1.1272 + "movq 32(%%rax), %%rcx\n\t" \
1.1273 + "movq 24(%%rax), %%rdx\n\t" \
1.1274 + "movq 16(%%rax), %%rsi\n\t" \
1.1275 + "movq 8(%%rax), %%rdi\n\t" \
1.1276 + "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1.1277 + VALGRIND_CALL_NOREDIR_RAX \
1.1278 + "addq $16, %%rsp\n" \
1.1279 + "addq $128,%%rsp\n\t" \
1.1280 + : /*out*/ "=a" (_res) \
1.1281 + : /*in*/ "a" (&_argvec[0]) \
1.1282 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1283 + ); \
1.1284 + lval = (__typeof__(lval)) _res; \
1.1285 + } while (0)
1.1286 +
1.1287 +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.1288 + arg7,arg8,arg9) \
1.1289 + do { \
1.1290 + volatile OrigFn _orig = (orig); \
1.1291 + volatile unsigned long _argvec[10]; \
1.1292 + volatile unsigned long _res; \
1.1293 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1294 + _argvec[1] = (unsigned long)(arg1); \
1.1295 + _argvec[2] = (unsigned long)(arg2); \
1.1296 + _argvec[3] = (unsigned long)(arg3); \
1.1297 + _argvec[4] = (unsigned long)(arg4); \
1.1298 + _argvec[5] = (unsigned long)(arg5); \
1.1299 + _argvec[6] = (unsigned long)(arg6); \
1.1300 + _argvec[7] = (unsigned long)(arg7); \
1.1301 + _argvec[8] = (unsigned long)(arg8); \
1.1302 + _argvec[9] = (unsigned long)(arg9); \
1.1303 + __asm__ volatile( \
1.1304 + "subq $128,%%rsp\n\t" \
1.1305 + "pushq 72(%%rax)\n\t" \
1.1306 + "pushq 64(%%rax)\n\t" \
1.1307 + "pushq 56(%%rax)\n\t" \
1.1308 + "movq 48(%%rax), %%r9\n\t" \
1.1309 + "movq 40(%%rax), %%r8\n\t" \
1.1310 + "movq 32(%%rax), %%rcx\n\t" \
1.1311 + "movq 24(%%rax), %%rdx\n\t" \
1.1312 + "movq 16(%%rax), %%rsi\n\t" \
1.1313 + "movq 8(%%rax), %%rdi\n\t" \
1.1314 + "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1.1315 + VALGRIND_CALL_NOREDIR_RAX \
1.1316 + "addq $24, %%rsp\n" \
1.1317 + "addq $128,%%rsp\n\t" \
1.1318 + : /*out*/ "=a" (_res) \
1.1319 + : /*in*/ "a" (&_argvec[0]) \
1.1320 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1321 + ); \
1.1322 + lval = (__typeof__(lval)) _res; \
1.1323 + } while (0)
1.1324 +
1.1325 +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.1326 + arg7,arg8,arg9,arg10) \
1.1327 + do { \
1.1328 + volatile OrigFn _orig = (orig); \
1.1329 + volatile unsigned long _argvec[11]; \
1.1330 + volatile unsigned long _res; \
1.1331 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1332 + _argvec[1] = (unsigned long)(arg1); \
1.1333 + _argvec[2] = (unsigned long)(arg2); \
1.1334 + _argvec[3] = (unsigned long)(arg3); \
1.1335 + _argvec[4] = (unsigned long)(arg4); \
1.1336 + _argvec[5] = (unsigned long)(arg5); \
1.1337 + _argvec[6] = (unsigned long)(arg6); \
1.1338 + _argvec[7] = (unsigned long)(arg7); \
1.1339 + _argvec[8] = (unsigned long)(arg8); \
1.1340 + _argvec[9] = (unsigned long)(arg9); \
1.1341 + _argvec[10] = (unsigned long)(arg10); \
1.1342 + __asm__ volatile( \
1.1343 + "subq $128,%%rsp\n\t" \
1.1344 + "pushq 80(%%rax)\n\t" \
1.1345 + "pushq 72(%%rax)\n\t" \
1.1346 + "pushq 64(%%rax)\n\t" \
1.1347 + "pushq 56(%%rax)\n\t" \
1.1348 + "movq 48(%%rax), %%r9\n\t" \
1.1349 + "movq 40(%%rax), %%r8\n\t" \
1.1350 + "movq 32(%%rax), %%rcx\n\t" \
1.1351 + "movq 24(%%rax), %%rdx\n\t" \
1.1352 + "movq 16(%%rax), %%rsi\n\t" \
1.1353 + "movq 8(%%rax), %%rdi\n\t" \
1.1354 + "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1.1355 + VALGRIND_CALL_NOREDIR_RAX \
1.1356 + "addq $32, %%rsp\n" \
1.1357 + "addq $128,%%rsp\n\t" \
1.1358 + : /*out*/ "=a" (_res) \
1.1359 + : /*in*/ "a" (&_argvec[0]) \
1.1360 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1361 + ); \
1.1362 + lval = (__typeof__(lval)) _res; \
1.1363 + } while (0)
1.1364 +
1.1365 +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.1366 + arg7,arg8,arg9,arg10,arg11) \
1.1367 + do { \
1.1368 + volatile OrigFn _orig = (orig); \
1.1369 + volatile unsigned long _argvec[12]; \
1.1370 + volatile unsigned long _res; \
1.1371 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1372 + _argvec[1] = (unsigned long)(arg1); \
1.1373 + _argvec[2] = (unsigned long)(arg2); \
1.1374 + _argvec[3] = (unsigned long)(arg3); \
1.1375 + _argvec[4] = (unsigned long)(arg4); \
1.1376 + _argvec[5] = (unsigned long)(arg5); \
1.1377 + _argvec[6] = (unsigned long)(arg6); \
1.1378 + _argvec[7] = (unsigned long)(arg7); \
1.1379 + _argvec[8] = (unsigned long)(arg8); \
1.1380 + _argvec[9] = (unsigned long)(arg9); \
1.1381 + _argvec[10] = (unsigned long)(arg10); \
1.1382 + _argvec[11] = (unsigned long)(arg11); \
1.1383 + __asm__ volatile( \
1.1384 + "subq $128,%%rsp\n\t" \
1.1385 + "pushq 88(%%rax)\n\t" \
1.1386 + "pushq 80(%%rax)\n\t" \
1.1387 + "pushq 72(%%rax)\n\t" \
1.1388 + "pushq 64(%%rax)\n\t" \
1.1389 + "pushq 56(%%rax)\n\t" \
1.1390 + "movq 48(%%rax), %%r9\n\t" \
1.1391 + "movq 40(%%rax), %%r8\n\t" \
1.1392 + "movq 32(%%rax), %%rcx\n\t" \
1.1393 + "movq 24(%%rax), %%rdx\n\t" \
1.1394 + "movq 16(%%rax), %%rsi\n\t" \
1.1395 + "movq 8(%%rax), %%rdi\n\t" \
1.1396 + "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1.1397 + VALGRIND_CALL_NOREDIR_RAX \
1.1398 + "addq $40, %%rsp\n" \
1.1399 + "addq $128,%%rsp\n\t" \
1.1400 + : /*out*/ "=a" (_res) \
1.1401 + : /*in*/ "a" (&_argvec[0]) \
1.1402 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1403 + ); \
1.1404 + lval = (__typeof__(lval)) _res; \
1.1405 + } while (0)
1.1406 +
1.1407 +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.1408 + arg7,arg8,arg9,arg10,arg11,arg12) \
1.1409 + do { \
1.1410 + volatile OrigFn _orig = (orig); \
1.1411 + volatile unsigned long _argvec[13]; \
1.1412 + volatile unsigned long _res; \
1.1413 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1414 + _argvec[1] = (unsigned long)(arg1); \
1.1415 + _argvec[2] = (unsigned long)(arg2); \
1.1416 + _argvec[3] = (unsigned long)(arg3); \
1.1417 + _argvec[4] = (unsigned long)(arg4); \
1.1418 + _argvec[5] = (unsigned long)(arg5); \
1.1419 + _argvec[6] = (unsigned long)(arg6); \
1.1420 + _argvec[7] = (unsigned long)(arg7); \
1.1421 + _argvec[8] = (unsigned long)(arg8); \
1.1422 + _argvec[9] = (unsigned long)(arg9); \
1.1423 + _argvec[10] = (unsigned long)(arg10); \
1.1424 + _argvec[11] = (unsigned long)(arg11); \
1.1425 + _argvec[12] = (unsigned long)(arg12); \
1.1426 + __asm__ volatile( \
1.1427 + "subq $128,%%rsp\n\t" \
1.1428 + "pushq 96(%%rax)\n\t" \
1.1429 + "pushq 88(%%rax)\n\t" \
1.1430 + "pushq 80(%%rax)\n\t" \
1.1431 + "pushq 72(%%rax)\n\t" \
1.1432 + "pushq 64(%%rax)\n\t" \
1.1433 + "pushq 56(%%rax)\n\t" \
1.1434 + "movq 48(%%rax), %%r9\n\t" \
1.1435 + "movq 40(%%rax), %%r8\n\t" \
1.1436 + "movq 32(%%rax), %%rcx\n\t" \
1.1437 + "movq 24(%%rax), %%rdx\n\t" \
1.1438 + "movq 16(%%rax), %%rsi\n\t" \
1.1439 + "movq 8(%%rax), %%rdi\n\t" \
1.1440 + "movq (%%rax), %%rax\n\t" /* target->%rax */ \
1.1441 + VALGRIND_CALL_NOREDIR_RAX \
1.1442 + "addq $48, %%rsp\n" \
1.1443 + "addq $128,%%rsp\n\t" \
1.1444 + : /*out*/ "=a" (_res) \
1.1445 + : /*in*/ "a" (&_argvec[0]) \
1.1446 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1447 + ); \
1.1448 + lval = (__typeof__(lval)) _res; \
1.1449 + } while (0)
1.1450 +
1.1451 +#endif /* PLAT_amd64_linux */
1.1452 +
1.1453 +/* ------------------------ ppc32-linux ------------------------ */
1.1454 +
1.1455 +#if defined(PLAT_ppc32_linux)
1.1456 +
1.1457 +/* This is useful for finding out about the on-stack stuff:
1.1458 +
1.1459 + extern int f9 ( int,int,int,int,int,int,int,int,int );
1.1460 + extern int f10 ( int,int,int,int,int,int,int,int,int,int );
1.1461 + extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
1.1462 + extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
1.1463 +
1.1464 + int g9 ( void ) {
1.1465 + return f9(11,22,33,44,55,66,77,88,99);
1.1466 + }
1.1467 + int g10 ( void ) {
1.1468 + return f10(11,22,33,44,55,66,77,88,99,110);
1.1469 + }
1.1470 + int g11 ( void ) {
1.1471 + return f11(11,22,33,44,55,66,77,88,99,110,121);
1.1472 + }
1.1473 + int g12 ( void ) {
1.1474 + return f12(11,22,33,44,55,66,77,88,99,110,121,132);
1.1475 + }
1.1476 +*/
1.1477 +
1.1478 +/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1.1479 +
1.1480 +/* These regs are trashed by the hidden call. */
1.1481 +#define __CALLER_SAVED_REGS \
1.1482 + "lr", "ctr", "xer", \
1.1483 + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1.1484 + "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1.1485 + "r11", "r12", "r13"
1.1486 +
1.1487 +/* These CALL_FN_ macros assume that on ppc32-linux,
1.1488 + sizeof(unsigned long) == 4. */
1.1489 +
1.1490 +#define CALL_FN_W_v(lval, orig) \
1.1491 + do { \
1.1492 + volatile OrigFn _orig = (orig); \
1.1493 + volatile unsigned long _argvec[1]; \
1.1494 + volatile unsigned long _res; \
1.1495 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1496 + __asm__ volatile( \
1.1497 + "mr 11,%1\n\t" \
1.1498 + "lwz 11,0(11)\n\t" /* target->r11 */ \
1.1499 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.1500 + "mr %0,3" \
1.1501 + : /*out*/ "=r" (_res) \
1.1502 + : /*in*/ "r" (&_argvec[0]) \
1.1503 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1504 + ); \
1.1505 + lval = (__typeof__(lval)) _res; \
1.1506 + } while (0)
1.1507 +
1.1508 +#define CALL_FN_W_W(lval, orig, arg1) \
1.1509 + do { \
1.1510 + volatile OrigFn _orig = (orig); \
1.1511 + volatile unsigned long _argvec[2]; \
1.1512 + volatile unsigned long _res; \
1.1513 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1514 + _argvec[1] = (unsigned long)arg1; \
1.1515 + __asm__ volatile( \
1.1516 + "mr 11,%1\n\t" \
1.1517 + "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1.1518 + "lwz 11,0(11)\n\t" /* target->r11 */ \
1.1519 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.1520 + "mr %0,3" \
1.1521 + : /*out*/ "=r" (_res) \
1.1522 + : /*in*/ "r" (&_argvec[0]) \
1.1523 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1524 + ); \
1.1525 + lval = (__typeof__(lval)) _res; \
1.1526 + } while (0)
1.1527 +
1.1528 +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1.1529 + do { \
1.1530 + volatile OrigFn _orig = (orig); \
1.1531 + volatile unsigned long _argvec[3]; \
1.1532 + volatile unsigned long _res; \
1.1533 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1534 + _argvec[1] = (unsigned long)arg1; \
1.1535 + _argvec[2] = (unsigned long)arg2; \
1.1536 + __asm__ volatile( \
1.1537 + "mr 11,%1\n\t" \
1.1538 + "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1.1539 + "lwz 4,8(11)\n\t" \
1.1540 + "lwz 11,0(11)\n\t" /* target->r11 */ \
1.1541 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.1542 + "mr %0,3" \
1.1543 + : /*out*/ "=r" (_res) \
1.1544 + : /*in*/ "r" (&_argvec[0]) \
1.1545 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1546 + ); \
1.1547 + lval = (__typeof__(lval)) _res; \
1.1548 + } while (0)
1.1549 +
1.1550 +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1.1551 + do { \
1.1552 + volatile OrigFn _orig = (orig); \
1.1553 + volatile unsigned long _argvec[4]; \
1.1554 + volatile unsigned long _res; \
1.1555 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1556 + _argvec[1] = (unsigned long)arg1; \
1.1557 + _argvec[2] = (unsigned long)arg2; \
1.1558 + _argvec[3] = (unsigned long)arg3; \
1.1559 + __asm__ volatile( \
1.1560 + "mr 11,%1\n\t" \
1.1561 + "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1.1562 + "lwz 4,8(11)\n\t" \
1.1563 + "lwz 5,12(11)\n\t" \
1.1564 + "lwz 11,0(11)\n\t" /* target->r11 */ \
1.1565 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.1566 + "mr %0,3" \
1.1567 + : /*out*/ "=r" (_res) \
1.1568 + : /*in*/ "r" (&_argvec[0]) \
1.1569 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1570 + ); \
1.1571 + lval = (__typeof__(lval)) _res; \
1.1572 + } while (0)
1.1573 +
1.1574 +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1.1575 + do { \
1.1576 + volatile OrigFn _orig = (orig); \
1.1577 + volatile unsigned long _argvec[5]; \
1.1578 + volatile unsigned long _res; \
1.1579 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1580 + _argvec[1] = (unsigned long)arg1; \
1.1581 + _argvec[2] = (unsigned long)arg2; \
1.1582 + _argvec[3] = (unsigned long)arg3; \
1.1583 + _argvec[4] = (unsigned long)arg4; \
1.1584 + __asm__ volatile( \
1.1585 + "mr 11,%1\n\t" \
1.1586 + "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1.1587 + "lwz 4,8(11)\n\t" \
1.1588 + "lwz 5,12(11)\n\t" \
1.1589 + "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1.1590 + "lwz 11,0(11)\n\t" /* target->r11 */ \
1.1591 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.1592 + "mr %0,3" \
1.1593 + : /*out*/ "=r" (_res) \
1.1594 + : /*in*/ "r" (&_argvec[0]) \
1.1595 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1596 + ); \
1.1597 + lval = (__typeof__(lval)) _res; \
1.1598 + } while (0)
1.1599 +
1.1600 +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1.1601 + do { \
1.1602 + volatile OrigFn _orig = (orig); \
1.1603 + volatile unsigned long _argvec[6]; \
1.1604 + volatile unsigned long _res; \
1.1605 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1606 + _argvec[1] = (unsigned long)arg1; \
1.1607 + _argvec[2] = (unsigned long)arg2; \
1.1608 + _argvec[3] = (unsigned long)arg3; \
1.1609 + _argvec[4] = (unsigned long)arg4; \
1.1610 + _argvec[5] = (unsigned long)arg5; \
1.1611 + __asm__ volatile( \
1.1612 + "mr 11,%1\n\t" \
1.1613 + "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1.1614 + "lwz 4,8(11)\n\t" \
1.1615 + "lwz 5,12(11)\n\t" \
1.1616 + "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1.1617 + "lwz 7,20(11)\n\t" \
1.1618 + "lwz 11,0(11)\n\t" /* target->r11 */ \
1.1619 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.1620 + "mr %0,3" \
1.1621 + : /*out*/ "=r" (_res) \
1.1622 + : /*in*/ "r" (&_argvec[0]) \
1.1623 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1624 + ); \
1.1625 + lval = (__typeof__(lval)) _res; \
1.1626 + } while (0)
1.1627 +
1.1628 +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1.1629 + do { \
1.1630 + volatile OrigFn _orig = (orig); \
1.1631 + volatile unsigned long _argvec[7]; \
1.1632 + volatile unsigned long _res; \
1.1633 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1634 + _argvec[1] = (unsigned long)arg1; \
1.1635 + _argvec[2] = (unsigned long)arg2; \
1.1636 + _argvec[3] = (unsigned long)arg3; \
1.1637 + _argvec[4] = (unsigned long)arg4; \
1.1638 + _argvec[5] = (unsigned long)arg5; \
1.1639 + _argvec[6] = (unsigned long)arg6; \
1.1640 + __asm__ volatile( \
1.1641 + "mr 11,%1\n\t" \
1.1642 + "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1.1643 + "lwz 4,8(11)\n\t" \
1.1644 + "lwz 5,12(11)\n\t" \
1.1645 + "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1.1646 + "lwz 7,20(11)\n\t" \
1.1647 + "lwz 8,24(11)\n\t" \
1.1648 + "lwz 11,0(11)\n\t" /* target->r11 */ \
1.1649 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.1650 + "mr %0,3" \
1.1651 + : /*out*/ "=r" (_res) \
1.1652 + : /*in*/ "r" (&_argvec[0]) \
1.1653 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1654 + ); \
1.1655 + lval = (__typeof__(lval)) _res; \
1.1656 + } while (0)
1.1657 +
1.1658 +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.1659 + arg7) \
1.1660 + do { \
1.1661 + volatile OrigFn _orig = (orig); \
1.1662 + volatile unsigned long _argvec[8]; \
1.1663 + volatile unsigned long _res; \
1.1664 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1665 + _argvec[1] = (unsigned long)arg1; \
1.1666 + _argvec[2] = (unsigned long)arg2; \
1.1667 + _argvec[3] = (unsigned long)arg3; \
1.1668 + _argvec[4] = (unsigned long)arg4; \
1.1669 + _argvec[5] = (unsigned long)arg5; \
1.1670 + _argvec[6] = (unsigned long)arg6; \
1.1671 + _argvec[7] = (unsigned long)arg7; \
1.1672 + __asm__ volatile( \
1.1673 + "mr 11,%1\n\t" \
1.1674 + "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1.1675 + "lwz 4,8(11)\n\t" \
1.1676 + "lwz 5,12(11)\n\t" \
1.1677 + "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1.1678 + "lwz 7,20(11)\n\t" \
1.1679 + "lwz 8,24(11)\n\t" \
1.1680 + "lwz 9,28(11)\n\t" \
1.1681 + "lwz 11,0(11)\n\t" /* target->r11 */ \
1.1682 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.1683 + "mr %0,3" \
1.1684 + : /*out*/ "=r" (_res) \
1.1685 + : /*in*/ "r" (&_argvec[0]) \
1.1686 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1687 + ); \
1.1688 + lval = (__typeof__(lval)) _res; \
1.1689 + } while (0)
1.1690 +
1.1691 +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.1692 + arg7,arg8) \
1.1693 + do { \
1.1694 + volatile OrigFn _orig = (orig); \
1.1695 + volatile unsigned long _argvec[9]; \
1.1696 + volatile unsigned long _res; \
1.1697 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1698 + _argvec[1] = (unsigned long)arg1; \
1.1699 + _argvec[2] = (unsigned long)arg2; \
1.1700 + _argvec[3] = (unsigned long)arg3; \
1.1701 + _argvec[4] = (unsigned long)arg4; \
1.1702 + _argvec[5] = (unsigned long)arg5; \
1.1703 + _argvec[6] = (unsigned long)arg6; \
1.1704 + _argvec[7] = (unsigned long)arg7; \
1.1705 + _argvec[8] = (unsigned long)arg8; \
1.1706 + __asm__ volatile( \
1.1707 + "mr 11,%1\n\t" \
1.1708 + "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1.1709 + "lwz 4,8(11)\n\t" \
1.1710 + "lwz 5,12(11)\n\t" \
1.1711 + "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1.1712 + "lwz 7,20(11)\n\t" \
1.1713 + "lwz 8,24(11)\n\t" \
1.1714 + "lwz 9,28(11)\n\t" \
1.1715 + "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1.1716 + "lwz 11,0(11)\n\t" /* target->r11 */ \
1.1717 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.1718 + "mr %0,3" \
1.1719 + : /*out*/ "=r" (_res) \
1.1720 + : /*in*/ "r" (&_argvec[0]) \
1.1721 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1722 + ); \
1.1723 + lval = (__typeof__(lval)) _res; \
1.1724 + } while (0)
1.1725 +
1.1726 +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.1727 + arg7,arg8,arg9) \
1.1728 + do { \
1.1729 + volatile OrigFn _orig = (orig); \
1.1730 + volatile unsigned long _argvec[10]; \
1.1731 + volatile unsigned long _res; \
1.1732 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1733 + _argvec[1] = (unsigned long)arg1; \
1.1734 + _argvec[2] = (unsigned long)arg2; \
1.1735 + _argvec[3] = (unsigned long)arg3; \
1.1736 + _argvec[4] = (unsigned long)arg4; \
1.1737 + _argvec[5] = (unsigned long)arg5; \
1.1738 + _argvec[6] = (unsigned long)arg6; \
1.1739 + _argvec[7] = (unsigned long)arg7; \
1.1740 + _argvec[8] = (unsigned long)arg8; \
1.1741 + _argvec[9] = (unsigned long)arg9; \
1.1742 + __asm__ volatile( \
1.1743 + "mr 11,%1\n\t" \
1.1744 + "addi 1,1,-16\n\t" \
1.1745 + /* arg9 */ \
1.1746 + "lwz 3,36(11)\n\t" \
1.1747 + "stw 3,8(1)\n\t" \
1.1748 + /* args1-8 */ \
1.1749 + "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1.1750 + "lwz 4,8(11)\n\t" \
1.1751 + "lwz 5,12(11)\n\t" \
1.1752 + "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1.1753 + "lwz 7,20(11)\n\t" \
1.1754 + "lwz 8,24(11)\n\t" \
1.1755 + "lwz 9,28(11)\n\t" \
1.1756 + "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1.1757 + "lwz 11,0(11)\n\t" /* target->r11 */ \
1.1758 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.1759 + "addi 1,1,16\n\t" \
1.1760 + "mr %0,3" \
1.1761 + : /*out*/ "=r" (_res) \
1.1762 + : /*in*/ "r" (&_argvec[0]) \
1.1763 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1764 + ); \
1.1765 + lval = (__typeof__(lval)) _res; \
1.1766 + } while (0)
1.1767 +
1.1768 +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.1769 + arg7,arg8,arg9,arg10) \
1.1770 + do { \
1.1771 + volatile OrigFn _orig = (orig); \
1.1772 + volatile unsigned long _argvec[11]; \
1.1773 + volatile unsigned long _res; \
1.1774 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1775 + _argvec[1] = (unsigned long)arg1; \
1.1776 + _argvec[2] = (unsigned long)arg2; \
1.1777 + _argvec[3] = (unsigned long)arg3; \
1.1778 + _argvec[4] = (unsigned long)arg4; \
1.1779 + _argvec[5] = (unsigned long)arg5; \
1.1780 + _argvec[6] = (unsigned long)arg6; \
1.1781 + _argvec[7] = (unsigned long)arg7; \
1.1782 + _argvec[8] = (unsigned long)arg8; \
1.1783 + _argvec[9] = (unsigned long)arg9; \
1.1784 + _argvec[10] = (unsigned long)arg10; \
1.1785 + __asm__ volatile( \
1.1786 + "mr 11,%1\n\t" \
1.1787 + "addi 1,1,-16\n\t" \
1.1788 + /* arg10 */ \
1.1789 + "lwz 3,40(11)\n\t" \
1.1790 + "stw 3,12(1)\n\t" \
1.1791 + /* arg9 */ \
1.1792 + "lwz 3,36(11)\n\t" \
1.1793 + "stw 3,8(1)\n\t" \
1.1794 + /* args1-8 */ \
1.1795 + "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1.1796 + "lwz 4,8(11)\n\t" \
1.1797 + "lwz 5,12(11)\n\t" \
1.1798 + "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1.1799 + "lwz 7,20(11)\n\t" \
1.1800 + "lwz 8,24(11)\n\t" \
1.1801 + "lwz 9,28(11)\n\t" \
1.1802 + "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1.1803 + "lwz 11,0(11)\n\t" /* target->r11 */ \
1.1804 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.1805 + "addi 1,1,16\n\t" \
1.1806 + "mr %0,3" \
1.1807 + : /*out*/ "=r" (_res) \
1.1808 + : /*in*/ "r" (&_argvec[0]) \
1.1809 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1810 + ); \
1.1811 + lval = (__typeof__(lval)) _res; \
1.1812 + } while (0)
1.1813 +
1.1814 +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.1815 + arg7,arg8,arg9,arg10,arg11) \
1.1816 + do { \
1.1817 + volatile OrigFn _orig = (orig); \
1.1818 + volatile unsigned long _argvec[12]; \
1.1819 + volatile unsigned long _res; \
1.1820 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1821 + _argvec[1] = (unsigned long)arg1; \
1.1822 + _argvec[2] = (unsigned long)arg2; \
1.1823 + _argvec[3] = (unsigned long)arg3; \
1.1824 + _argvec[4] = (unsigned long)arg4; \
1.1825 + _argvec[5] = (unsigned long)arg5; \
1.1826 + _argvec[6] = (unsigned long)arg6; \
1.1827 + _argvec[7] = (unsigned long)arg7; \
1.1828 + _argvec[8] = (unsigned long)arg8; \
1.1829 + _argvec[9] = (unsigned long)arg9; \
1.1830 + _argvec[10] = (unsigned long)arg10; \
1.1831 + _argvec[11] = (unsigned long)arg11; \
1.1832 + __asm__ volatile( \
1.1833 + "mr 11,%1\n\t" \
1.1834 + "addi 1,1,-32\n\t" \
1.1835 + /* arg11 */ \
1.1836 + "lwz 3,44(11)\n\t" \
1.1837 + "stw 3,16(1)\n\t" \
1.1838 + /* arg10 */ \
1.1839 + "lwz 3,40(11)\n\t" \
1.1840 + "stw 3,12(1)\n\t" \
1.1841 + /* arg9 */ \
1.1842 + "lwz 3,36(11)\n\t" \
1.1843 + "stw 3,8(1)\n\t" \
1.1844 + /* args1-8 */ \
1.1845 + "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1.1846 + "lwz 4,8(11)\n\t" \
1.1847 + "lwz 5,12(11)\n\t" \
1.1848 + "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1.1849 + "lwz 7,20(11)\n\t" \
1.1850 + "lwz 8,24(11)\n\t" \
1.1851 + "lwz 9,28(11)\n\t" \
1.1852 + "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1.1853 + "lwz 11,0(11)\n\t" /* target->r11 */ \
1.1854 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.1855 + "addi 1,1,32\n\t" \
1.1856 + "mr %0,3" \
1.1857 + : /*out*/ "=r" (_res) \
1.1858 + : /*in*/ "r" (&_argvec[0]) \
1.1859 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1860 + ); \
1.1861 + lval = (__typeof__(lval)) _res; \
1.1862 + } while (0)
1.1863 +
1.1864 +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.1865 + arg7,arg8,arg9,arg10,arg11,arg12) \
1.1866 + do { \
1.1867 + volatile OrigFn _orig = (orig); \
1.1868 + volatile unsigned long _argvec[13]; \
1.1869 + volatile unsigned long _res; \
1.1870 + _argvec[0] = (unsigned long)_orig.nraddr; \
1.1871 + _argvec[1] = (unsigned long)arg1; \
1.1872 + _argvec[2] = (unsigned long)arg2; \
1.1873 + _argvec[3] = (unsigned long)arg3; \
1.1874 + _argvec[4] = (unsigned long)arg4; \
1.1875 + _argvec[5] = (unsigned long)arg5; \
1.1876 + _argvec[6] = (unsigned long)arg6; \
1.1877 + _argvec[7] = (unsigned long)arg7; \
1.1878 + _argvec[8] = (unsigned long)arg8; \
1.1879 + _argvec[9] = (unsigned long)arg9; \
1.1880 + _argvec[10] = (unsigned long)arg10; \
1.1881 + _argvec[11] = (unsigned long)arg11; \
1.1882 + _argvec[12] = (unsigned long)arg12; \
1.1883 + __asm__ volatile( \
1.1884 + "mr 11,%1\n\t" \
1.1885 + "addi 1,1,-32\n\t" \
1.1886 + /* arg12 */ \
1.1887 + "lwz 3,48(11)\n\t" \
1.1888 + "stw 3,20(1)\n\t" \
1.1889 + /* arg11 */ \
1.1890 + "lwz 3,44(11)\n\t" \
1.1891 + "stw 3,16(1)\n\t" \
1.1892 + /* arg10 */ \
1.1893 + "lwz 3,40(11)\n\t" \
1.1894 + "stw 3,12(1)\n\t" \
1.1895 + /* arg9 */ \
1.1896 + "lwz 3,36(11)\n\t" \
1.1897 + "stw 3,8(1)\n\t" \
1.1898 + /* args1-8 */ \
1.1899 + "lwz 3,4(11)\n\t" /* arg1->r3 */ \
1.1900 + "lwz 4,8(11)\n\t" \
1.1901 + "lwz 5,12(11)\n\t" \
1.1902 + "lwz 6,16(11)\n\t" /* arg4->r6 */ \
1.1903 + "lwz 7,20(11)\n\t" \
1.1904 + "lwz 8,24(11)\n\t" \
1.1905 + "lwz 9,28(11)\n\t" \
1.1906 + "lwz 10,32(11)\n\t" /* arg8->r10 */ \
1.1907 + "lwz 11,0(11)\n\t" /* target->r11 */ \
1.1908 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.1909 + "addi 1,1,32\n\t" \
1.1910 + "mr %0,3" \
1.1911 + : /*out*/ "=r" (_res) \
1.1912 + : /*in*/ "r" (&_argvec[0]) \
1.1913 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1914 + ); \
1.1915 + lval = (__typeof__(lval)) _res; \
1.1916 + } while (0)
1.1917 +
1.1918 +#endif /* PLAT_ppc32_linux */
1.1919 +
1.1920 +/* ------------------------ ppc64-linux ------------------------ */
1.1921 +
1.1922 +#if defined(PLAT_ppc64_linux)
1.1923 +
1.1924 +/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1.1925 +
1.1926 +/* These regs are trashed by the hidden call. */
1.1927 +#define __CALLER_SAVED_REGS \
1.1928 + "lr", "ctr", "xer", \
1.1929 + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1.1930 + "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1.1931 + "r11", "r12", "r13"
1.1932 +
1.1933 +/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
1.1934 + long) == 8. */
1.1935 +
1.1936 +#define CALL_FN_W_v(lval, orig) \
1.1937 + do { \
1.1938 + volatile OrigFn _orig = (orig); \
1.1939 + volatile unsigned long _argvec[3+0]; \
1.1940 + volatile unsigned long _res; \
1.1941 + /* _argvec[0] holds current r2 across the call */ \
1.1942 + _argvec[1] = (unsigned long)_orig.r2; \
1.1943 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.1944 + __asm__ volatile( \
1.1945 + "mr 11,%1\n\t" \
1.1946 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.1947 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.1948 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.1949 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.1950 + "mr 11,%1\n\t" \
1.1951 + "mr %0,3\n\t" \
1.1952 + "ld 2,-16(11)" /* restore tocptr */ \
1.1953 + : /*out*/ "=r" (_res) \
1.1954 + : /*in*/ "r" (&_argvec[2]) \
1.1955 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1956 + ); \
1.1957 + lval = (__typeof__(lval)) _res; \
1.1958 + } while (0)
1.1959 +
1.1960 +#define CALL_FN_W_W(lval, orig, arg1) \
1.1961 + do { \
1.1962 + volatile OrigFn _orig = (orig); \
1.1963 + volatile unsigned long _argvec[3+1]; \
1.1964 + volatile unsigned long _res; \
1.1965 + /* _argvec[0] holds current r2 across the call */ \
1.1966 + _argvec[1] = (unsigned long)_orig.r2; \
1.1967 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.1968 + _argvec[2+1] = (unsigned long)arg1; \
1.1969 + __asm__ volatile( \
1.1970 + "mr 11,%1\n\t" \
1.1971 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.1972 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.1973 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.1974 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.1975 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.1976 + "mr 11,%1\n\t" \
1.1977 + "mr %0,3\n\t" \
1.1978 + "ld 2,-16(11)" /* restore tocptr */ \
1.1979 + : /*out*/ "=r" (_res) \
1.1980 + : /*in*/ "r" (&_argvec[2]) \
1.1981 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.1982 + ); \
1.1983 + lval = (__typeof__(lval)) _res; \
1.1984 + } while (0)
1.1985 +
1.1986 +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1.1987 + do { \
1.1988 + volatile OrigFn _orig = (orig); \
1.1989 + volatile unsigned long _argvec[3+2]; \
1.1990 + volatile unsigned long _res; \
1.1991 + /* _argvec[0] holds current r2 across the call */ \
1.1992 + _argvec[1] = (unsigned long)_orig.r2; \
1.1993 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.1994 + _argvec[2+1] = (unsigned long)arg1; \
1.1995 + _argvec[2+2] = (unsigned long)arg2; \
1.1996 + __asm__ volatile( \
1.1997 + "mr 11,%1\n\t" \
1.1998 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.1999 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.2000 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.2001 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.2002 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.2003 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2004 + "mr 11,%1\n\t" \
1.2005 + "mr %0,3\n\t" \
1.2006 + "ld 2,-16(11)" /* restore tocptr */ \
1.2007 + : /*out*/ "=r" (_res) \
1.2008 + : /*in*/ "r" (&_argvec[2]) \
1.2009 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2010 + ); \
1.2011 + lval = (__typeof__(lval)) _res; \
1.2012 + } while (0)
1.2013 +
1.2014 +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1.2015 + do { \
1.2016 + volatile OrigFn _orig = (orig); \
1.2017 + volatile unsigned long _argvec[3+3]; \
1.2018 + volatile unsigned long _res; \
1.2019 + /* _argvec[0] holds current r2 across the call */ \
1.2020 + _argvec[1] = (unsigned long)_orig.r2; \
1.2021 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2022 + _argvec[2+1] = (unsigned long)arg1; \
1.2023 + _argvec[2+2] = (unsigned long)arg2; \
1.2024 + _argvec[2+3] = (unsigned long)arg3; \
1.2025 + __asm__ volatile( \
1.2026 + "mr 11,%1\n\t" \
1.2027 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.2028 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.2029 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.2030 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.2031 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.2032 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.2033 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2034 + "mr 11,%1\n\t" \
1.2035 + "mr %0,3\n\t" \
1.2036 + "ld 2,-16(11)" /* restore tocptr */ \
1.2037 + : /*out*/ "=r" (_res) \
1.2038 + : /*in*/ "r" (&_argvec[2]) \
1.2039 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2040 + ); \
1.2041 + lval = (__typeof__(lval)) _res; \
1.2042 + } while (0)
1.2043 +
1.2044 +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1.2045 + do { \
1.2046 + volatile OrigFn _orig = (orig); \
1.2047 + volatile unsigned long _argvec[3+4]; \
1.2048 + volatile unsigned long _res; \
1.2049 + /* _argvec[0] holds current r2 across the call */ \
1.2050 + _argvec[1] = (unsigned long)_orig.r2; \
1.2051 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2052 + _argvec[2+1] = (unsigned long)arg1; \
1.2053 + _argvec[2+2] = (unsigned long)arg2; \
1.2054 + _argvec[2+3] = (unsigned long)arg3; \
1.2055 + _argvec[2+4] = (unsigned long)arg4; \
1.2056 + __asm__ volatile( \
1.2057 + "mr 11,%1\n\t" \
1.2058 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.2059 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.2060 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.2061 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.2062 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.2063 + "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1.2064 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.2065 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2066 + "mr 11,%1\n\t" \
1.2067 + "mr %0,3\n\t" \
1.2068 + "ld 2,-16(11)" /* restore tocptr */ \
1.2069 + : /*out*/ "=r" (_res) \
1.2070 + : /*in*/ "r" (&_argvec[2]) \
1.2071 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2072 + ); \
1.2073 + lval = (__typeof__(lval)) _res; \
1.2074 + } while (0)
1.2075 +
1.2076 +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1.2077 + do { \
1.2078 + volatile OrigFn _orig = (orig); \
1.2079 + volatile unsigned long _argvec[3+5]; \
1.2080 + volatile unsigned long _res; \
1.2081 + /* _argvec[0] holds current r2 across the call */ \
1.2082 + _argvec[1] = (unsigned long)_orig.r2; \
1.2083 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2084 + _argvec[2+1] = (unsigned long)arg1; \
1.2085 + _argvec[2+2] = (unsigned long)arg2; \
1.2086 + _argvec[2+3] = (unsigned long)arg3; \
1.2087 + _argvec[2+4] = (unsigned long)arg4; \
1.2088 + _argvec[2+5] = (unsigned long)arg5; \
1.2089 + __asm__ volatile( \
1.2090 + "mr 11,%1\n\t" \
1.2091 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.2092 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.2093 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.2094 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.2095 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.2096 + "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1.2097 + "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1.2098 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.2099 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2100 + "mr 11,%1\n\t" \
1.2101 + "mr %0,3\n\t" \
1.2102 + "ld 2,-16(11)" /* restore tocptr */ \
1.2103 + : /*out*/ "=r" (_res) \
1.2104 + : /*in*/ "r" (&_argvec[2]) \
1.2105 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2106 + ); \
1.2107 + lval = (__typeof__(lval)) _res; \
1.2108 + } while (0)
1.2109 +
1.2110 +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1.2111 + do { \
1.2112 + volatile OrigFn _orig = (orig); \
1.2113 + volatile unsigned long _argvec[3+6]; \
1.2114 + volatile unsigned long _res; \
1.2115 + /* _argvec[0] holds current r2 across the call */ \
1.2116 + _argvec[1] = (unsigned long)_orig.r2; \
1.2117 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2118 + _argvec[2+1] = (unsigned long)arg1; \
1.2119 + _argvec[2+2] = (unsigned long)arg2; \
1.2120 + _argvec[2+3] = (unsigned long)arg3; \
1.2121 + _argvec[2+4] = (unsigned long)arg4; \
1.2122 + _argvec[2+5] = (unsigned long)arg5; \
1.2123 + _argvec[2+6] = (unsigned long)arg6; \
1.2124 + __asm__ volatile( \
1.2125 + "mr 11,%1\n\t" \
1.2126 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.2127 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.2128 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.2129 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.2130 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.2131 + "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1.2132 + "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1.2133 + "ld 8, 48(11)\n\t" /* arg6->r8 */ \
1.2134 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.2135 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2136 + "mr 11,%1\n\t" \
1.2137 + "mr %0,3\n\t" \
1.2138 + "ld 2,-16(11)" /* restore tocptr */ \
1.2139 + : /*out*/ "=r" (_res) \
1.2140 + : /*in*/ "r" (&_argvec[2]) \
1.2141 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2142 + ); \
1.2143 + lval = (__typeof__(lval)) _res; \
1.2144 + } while (0)
1.2145 +
1.2146 +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.2147 + arg7) \
1.2148 + do { \
1.2149 + volatile OrigFn _orig = (orig); \
1.2150 + volatile unsigned long _argvec[3+7]; \
1.2151 + volatile unsigned long _res; \
1.2152 + /* _argvec[0] holds current r2 across the call */ \
1.2153 + _argvec[1] = (unsigned long)_orig.r2; \
1.2154 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2155 + _argvec[2+1] = (unsigned long)arg1; \
1.2156 + _argvec[2+2] = (unsigned long)arg2; \
1.2157 + _argvec[2+3] = (unsigned long)arg3; \
1.2158 + _argvec[2+4] = (unsigned long)arg4; \
1.2159 + _argvec[2+5] = (unsigned long)arg5; \
1.2160 + _argvec[2+6] = (unsigned long)arg6; \
1.2161 + _argvec[2+7] = (unsigned long)arg7; \
1.2162 + __asm__ volatile( \
1.2163 + "mr 11,%1\n\t" \
1.2164 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.2165 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.2166 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.2167 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.2168 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.2169 + "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1.2170 + "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1.2171 + "ld 8, 48(11)\n\t" /* arg6->r8 */ \
1.2172 + "ld 9, 56(11)\n\t" /* arg7->r9 */ \
1.2173 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.2174 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2175 + "mr 11,%1\n\t" \
1.2176 + "mr %0,3\n\t" \
1.2177 + "ld 2,-16(11)" /* restore tocptr */ \
1.2178 + : /*out*/ "=r" (_res) \
1.2179 + : /*in*/ "r" (&_argvec[2]) \
1.2180 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2181 + ); \
1.2182 + lval = (__typeof__(lval)) _res; \
1.2183 + } while (0)
1.2184 +
1.2185 +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.2186 + arg7,arg8) \
1.2187 + do { \
1.2188 + volatile OrigFn _orig = (orig); \
1.2189 + volatile unsigned long _argvec[3+8]; \
1.2190 + volatile unsigned long _res; \
1.2191 + /* _argvec[0] holds current r2 across the call */ \
1.2192 + _argvec[1] = (unsigned long)_orig.r2; \
1.2193 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2194 + _argvec[2+1] = (unsigned long)arg1; \
1.2195 + _argvec[2+2] = (unsigned long)arg2; \
1.2196 + _argvec[2+3] = (unsigned long)arg3; \
1.2197 + _argvec[2+4] = (unsigned long)arg4; \
1.2198 + _argvec[2+5] = (unsigned long)arg5; \
1.2199 + _argvec[2+6] = (unsigned long)arg6; \
1.2200 + _argvec[2+7] = (unsigned long)arg7; \
1.2201 + _argvec[2+8] = (unsigned long)arg8; \
1.2202 + __asm__ volatile( \
1.2203 + "mr 11,%1\n\t" \
1.2204 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.2205 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.2206 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.2207 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.2208 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.2209 + "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1.2210 + "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1.2211 + "ld 8, 48(11)\n\t" /* arg6->r8 */ \
1.2212 + "ld 9, 56(11)\n\t" /* arg7->r9 */ \
1.2213 + "ld 10, 64(11)\n\t" /* arg8->r10 */ \
1.2214 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.2215 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2216 + "mr 11,%1\n\t" \
1.2217 + "mr %0,3\n\t" \
1.2218 + "ld 2,-16(11)" /* restore tocptr */ \
1.2219 + : /*out*/ "=r" (_res) \
1.2220 + : /*in*/ "r" (&_argvec[2]) \
1.2221 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2222 + ); \
1.2223 + lval = (__typeof__(lval)) _res; \
1.2224 + } while (0)
1.2225 +
1.2226 +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.2227 + arg7,arg8,arg9) \
1.2228 + do { \
1.2229 + volatile OrigFn _orig = (orig); \
1.2230 + volatile unsigned long _argvec[3+9]; \
1.2231 + volatile unsigned long _res; \
1.2232 + /* _argvec[0] holds current r2 across the call */ \
1.2233 + _argvec[1] = (unsigned long)_orig.r2; \
1.2234 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2235 + _argvec[2+1] = (unsigned long)arg1; \
1.2236 + _argvec[2+2] = (unsigned long)arg2; \
1.2237 + _argvec[2+3] = (unsigned long)arg3; \
1.2238 + _argvec[2+4] = (unsigned long)arg4; \
1.2239 + _argvec[2+5] = (unsigned long)arg5; \
1.2240 + _argvec[2+6] = (unsigned long)arg6; \
1.2241 + _argvec[2+7] = (unsigned long)arg7; \
1.2242 + _argvec[2+8] = (unsigned long)arg8; \
1.2243 + _argvec[2+9] = (unsigned long)arg9; \
1.2244 + __asm__ volatile( \
1.2245 + "mr 11,%1\n\t" \
1.2246 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.2247 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.2248 + "addi 1,1,-128\n\t" /* expand stack frame */ \
1.2249 + /* arg9 */ \
1.2250 + "ld 3,72(11)\n\t" \
1.2251 + "std 3,112(1)\n\t" \
1.2252 + /* args1-8 */ \
1.2253 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.2254 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.2255 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.2256 + "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1.2257 + "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1.2258 + "ld 8, 48(11)\n\t" /* arg6->r8 */ \
1.2259 + "ld 9, 56(11)\n\t" /* arg7->r9 */ \
1.2260 + "ld 10, 64(11)\n\t" /* arg8->r10 */ \
1.2261 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.2262 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2263 + "mr 11,%1\n\t" \
1.2264 + "mr %0,3\n\t" \
1.2265 + "ld 2,-16(11)\n\t" /* restore tocptr */ \
1.2266 + "addi 1,1,128" /* restore frame */ \
1.2267 + : /*out*/ "=r" (_res) \
1.2268 + : /*in*/ "r" (&_argvec[2]) \
1.2269 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2270 + ); \
1.2271 + lval = (__typeof__(lval)) _res; \
1.2272 + } while (0)
1.2273 +
1.2274 +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.2275 + arg7,arg8,arg9,arg10) \
1.2276 + do { \
1.2277 + volatile OrigFn _orig = (orig); \
1.2278 + volatile unsigned long _argvec[3+10]; \
1.2279 + volatile unsigned long _res; \
1.2280 + /* _argvec[0] holds current r2 across the call */ \
1.2281 + _argvec[1] = (unsigned long)_orig.r2; \
1.2282 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2283 + _argvec[2+1] = (unsigned long)arg1; \
1.2284 + _argvec[2+2] = (unsigned long)arg2; \
1.2285 + _argvec[2+3] = (unsigned long)arg3; \
1.2286 + _argvec[2+4] = (unsigned long)arg4; \
1.2287 + _argvec[2+5] = (unsigned long)arg5; \
1.2288 + _argvec[2+6] = (unsigned long)arg6; \
1.2289 + _argvec[2+7] = (unsigned long)arg7; \
1.2290 + _argvec[2+8] = (unsigned long)arg8; \
1.2291 + _argvec[2+9] = (unsigned long)arg9; \
1.2292 + _argvec[2+10] = (unsigned long)arg10; \
1.2293 + __asm__ volatile( \
1.2294 + "mr 11,%1\n\t" \
1.2295 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.2296 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.2297 + "addi 1,1,-128\n\t" /* expand stack frame */ \
1.2298 + /* arg10 */ \
1.2299 + "ld 3,80(11)\n\t" \
1.2300 + "std 3,120(1)\n\t" \
1.2301 + /* arg9 */ \
1.2302 + "ld 3,72(11)\n\t" \
1.2303 + "std 3,112(1)\n\t" \
1.2304 + /* args1-8 */ \
1.2305 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.2306 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.2307 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.2308 + "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1.2309 + "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1.2310 + "ld 8, 48(11)\n\t" /* arg6->r8 */ \
1.2311 + "ld 9, 56(11)\n\t" /* arg7->r9 */ \
1.2312 + "ld 10, 64(11)\n\t" /* arg8->r10 */ \
1.2313 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.2314 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2315 + "mr 11,%1\n\t" \
1.2316 + "mr %0,3\n\t" \
1.2317 + "ld 2,-16(11)\n\t" /* restore tocptr */ \
1.2318 + "addi 1,1,128" /* restore frame */ \
1.2319 + : /*out*/ "=r" (_res) \
1.2320 + : /*in*/ "r" (&_argvec[2]) \
1.2321 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2322 + ); \
1.2323 + lval = (__typeof__(lval)) _res; \
1.2324 + } while (0)
1.2325 +
1.2326 +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.2327 + arg7,arg8,arg9,arg10,arg11) \
1.2328 + do { \
1.2329 + volatile OrigFn _orig = (orig); \
1.2330 + volatile unsigned long _argvec[3+11]; \
1.2331 + volatile unsigned long _res; \
1.2332 + /* _argvec[0] holds current r2 across the call */ \
1.2333 + _argvec[1] = (unsigned long)_orig.r2; \
1.2334 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2335 + _argvec[2+1] = (unsigned long)arg1; \
1.2336 + _argvec[2+2] = (unsigned long)arg2; \
1.2337 + _argvec[2+3] = (unsigned long)arg3; \
1.2338 + _argvec[2+4] = (unsigned long)arg4; \
1.2339 + _argvec[2+5] = (unsigned long)arg5; \
1.2340 + _argvec[2+6] = (unsigned long)arg6; \
1.2341 + _argvec[2+7] = (unsigned long)arg7; \
1.2342 + _argvec[2+8] = (unsigned long)arg8; \
1.2343 + _argvec[2+9] = (unsigned long)arg9; \
1.2344 + _argvec[2+10] = (unsigned long)arg10; \
1.2345 + _argvec[2+11] = (unsigned long)arg11; \
1.2346 + __asm__ volatile( \
1.2347 + "mr 11,%1\n\t" \
1.2348 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.2349 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.2350 + "addi 1,1,-144\n\t" /* expand stack frame */ \
1.2351 + /* arg11 */ \
1.2352 + "ld 3,88(11)\n\t" \
1.2353 + "std 3,128(1)\n\t" \
1.2354 + /* arg10 */ \
1.2355 + "ld 3,80(11)\n\t" \
1.2356 + "std 3,120(1)\n\t" \
1.2357 + /* arg9 */ \
1.2358 + "ld 3,72(11)\n\t" \
1.2359 + "std 3,112(1)\n\t" \
1.2360 + /* args1-8 */ \
1.2361 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.2362 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.2363 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.2364 + "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1.2365 + "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1.2366 + "ld 8, 48(11)\n\t" /* arg6->r8 */ \
1.2367 + "ld 9, 56(11)\n\t" /* arg7->r9 */ \
1.2368 + "ld 10, 64(11)\n\t" /* arg8->r10 */ \
1.2369 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.2370 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2371 + "mr 11,%1\n\t" \
1.2372 + "mr %0,3\n\t" \
1.2373 + "ld 2,-16(11)\n\t" /* restore tocptr */ \
1.2374 + "addi 1,1,144" /* restore frame */ \
1.2375 + : /*out*/ "=r" (_res) \
1.2376 + : /*in*/ "r" (&_argvec[2]) \
1.2377 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2378 + ); \
1.2379 + lval = (__typeof__(lval)) _res; \
1.2380 + } while (0)
1.2381 +
1.2382 +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.2383 + arg7,arg8,arg9,arg10,arg11,arg12) \
1.2384 + do { \
1.2385 + volatile OrigFn _orig = (orig); \
1.2386 + volatile unsigned long _argvec[3+12]; \
1.2387 + volatile unsigned long _res; \
1.2388 + /* _argvec[0] holds current r2 across the call */ \
1.2389 + _argvec[1] = (unsigned long)_orig.r2; \
1.2390 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2391 + _argvec[2+1] = (unsigned long)arg1; \
1.2392 + _argvec[2+2] = (unsigned long)arg2; \
1.2393 + _argvec[2+3] = (unsigned long)arg3; \
1.2394 + _argvec[2+4] = (unsigned long)arg4; \
1.2395 + _argvec[2+5] = (unsigned long)arg5; \
1.2396 + _argvec[2+6] = (unsigned long)arg6; \
1.2397 + _argvec[2+7] = (unsigned long)arg7; \
1.2398 + _argvec[2+8] = (unsigned long)arg8; \
1.2399 + _argvec[2+9] = (unsigned long)arg9; \
1.2400 + _argvec[2+10] = (unsigned long)arg10; \
1.2401 + _argvec[2+11] = (unsigned long)arg11; \
1.2402 + _argvec[2+12] = (unsigned long)arg12; \
1.2403 + __asm__ volatile( \
1.2404 + "mr 11,%1\n\t" \
1.2405 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.2406 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.2407 + "addi 1,1,-144\n\t" /* expand stack frame */ \
1.2408 + /* arg12 */ \
1.2409 + "ld 3,96(11)\n\t" \
1.2410 + "std 3,136(1)\n\t" \
1.2411 + /* arg11 */ \
1.2412 + "ld 3,88(11)\n\t" \
1.2413 + "std 3,128(1)\n\t" \
1.2414 + /* arg10 */ \
1.2415 + "ld 3,80(11)\n\t" \
1.2416 + "std 3,120(1)\n\t" \
1.2417 + /* arg9 */ \
1.2418 + "ld 3,72(11)\n\t" \
1.2419 + "std 3,112(1)\n\t" \
1.2420 + /* args1-8 */ \
1.2421 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.2422 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.2423 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.2424 + "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1.2425 + "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1.2426 + "ld 8, 48(11)\n\t" /* arg6->r8 */ \
1.2427 + "ld 9, 56(11)\n\t" /* arg7->r9 */ \
1.2428 + "ld 10, 64(11)\n\t" /* arg8->r10 */ \
1.2429 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.2430 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2431 + "mr 11,%1\n\t" \
1.2432 + "mr %0,3\n\t" \
1.2433 + "ld 2,-16(11)\n\t" /* restore tocptr */ \
1.2434 + "addi 1,1,144" /* restore frame */ \
1.2435 + : /*out*/ "=r" (_res) \
1.2436 + : /*in*/ "r" (&_argvec[2]) \
1.2437 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2438 + ); \
1.2439 + lval = (__typeof__(lval)) _res; \
1.2440 + } while (0)
1.2441 +
1.2442 +#endif /* PLAT_ppc64_linux */
1.2443 +
1.2444 +/* ------------------------ ppc32-aix5 ------------------------- */
1.2445 +
1.2446 +#if defined(PLAT_ppc32_aix5)
1.2447 +
1.2448 +/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1.2449 +
1.2450 +/* These regs are trashed by the hidden call. */
1.2451 +#define __CALLER_SAVED_REGS \
1.2452 + "lr", "ctr", "xer", \
1.2453 + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1.2454 + "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1.2455 + "r11", "r12", "r13"
1.2456 +
1.2457 +/* Expand the stack frame, copying enough info that unwinding
1.2458 + still works. Trashes r3. */
1.2459 +
1.2460 +#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
1.2461 + "addi 1,1,-" #_n_fr "\n\t" \
1.2462 + "lwz 3," #_n_fr "(1)\n\t" \
1.2463 + "stw 3,0(1)\n\t"
1.2464 +
1.2465 +#define VG_CONTRACT_FRAME_BY(_n_fr) \
1.2466 + "addi 1,1," #_n_fr "\n\t"
1.2467 +
1.2468 +/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
1.2469 + long) == 4. */
1.2470 +
1.2471 +#define CALL_FN_W_v(lval, orig) \
1.2472 + do { \
1.2473 + volatile OrigFn _orig = (orig); \
1.2474 + volatile unsigned long _argvec[3+0]; \
1.2475 + volatile unsigned long _res; \
1.2476 + /* _argvec[0] holds current r2 across the call */ \
1.2477 + _argvec[1] = (unsigned long)_orig.r2; \
1.2478 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2479 + __asm__ volatile( \
1.2480 + "mr 11,%1\n\t" \
1.2481 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.2482 + "stw 2,-8(11)\n\t" /* save tocptr */ \
1.2483 + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
1.2484 + "lwz 11, 0(11)\n\t" /* target->r11 */ \
1.2485 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2486 + "mr 11,%1\n\t" \
1.2487 + "mr %0,3\n\t" \
1.2488 + "lwz 2,-8(11)\n\t" /* restore tocptr */ \
1.2489 + VG_CONTRACT_FRAME_BY(512) \
1.2490 + : /*out*/ "=r" (_res) \
1.2491 + : /*in*/ "r" (&_argvec[2]) \
1.2492 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2493 + ); \
1.2494 + lval = (__typeof__(lval)) _res; \
1.2495 + } while (0)
1.2496 +
1.2497 +#define CALL_FN_W_W(lval, orig, arg1) \
1.2498 + do { \
1.2499 + volatile OrigFn _orig = (orig); \
1.2500 + volatile unsigned long _argvec[3+1]; \
1.2501 + volatile unsigned long _res; \
1.2502 + /* _argvec[0] holds current r2 across the call */ \
1.2503 + _argvec[1] = (unsigned long)_orig.r2; \
1.2504 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2505 + _argvec[2+1] = (unsigned long)arg1; \
1.2506 + __asm__ volatile( \
1.2507 + "mr 11,%1\n\t" \
1.2508 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.2509 + "stw 2,-8(11)\n\t" /* save tocptr */ \
1.2510 + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
1.2511 + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
1.2512 + "lwz 11, 0(11)\n\t" /* target->r11 */ \
1.2513 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2514 + "mr 11,%1\n\t" \
1.2515 + "mr %0,3\n\t" \
1.2516 + "lwz 2,-8(11)\n\t" /* restore tocptr */ \
1.2517 + VG_CONTRACT_FRAME_BY(512) \
1.2518 + : /*out*/ "=r" (_res) \
1.2519 + : /*in*/ "r" (&_argvec[2]) \
1.2520 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2521 + ); \
1.2522 + lval = (__typeof__(lval)) _res; \
1.2523 + } while (0)
1.2524 +
1.2525 +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1.2526 + do { \
1.2527 + volatile OrigFn _orig = (orig); \
1.2528 + volatile unsigned long _argvec[3+2]; \
1.2529 + volatile unsigned long _res; \
1.2530 + /* _argvec[0] holds current r2 across the call */ \
1.2531 + _argvec[1] = (unsigned long)_orig.r2; \
1.2532 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2533 + _argvec[2+1] = (unsigned long)arg1; \
1.2534 + _argvec[2+2] = (unsigned long)arg2; \
1.2535 + __asm__ volatile( \
1.2536 + "mr 11,%1\n\t" \
1.2537 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.2538 + "stw 2,-8(11)\n\t" /* save tocptr */ \
1.2539 + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
1.2540 + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
1.2541 + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
1.2542 + "lwz 11, 0(11)\n\t" /* target->r11 */ \
1.2543 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2544 + "mr 11,%1\n\t" \
1.2545 + "mr %0,3\n\t" \
1.2546 + "lwz 2,-8(11)\n\t" /* restore tocptr */ \
1.2547 + VG_CONTRACT_FRAME_BY(512) \
1.2548 + : /*out*/ "=r" (_res) \
1.2549 + : /*in*/ "r" (&_argvec[2]) \
1.2550 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2551 + ); \
1.2552 + lval = (__typeof__(lval)) _res; \
1.2553 + } while (0)
1.2554 +
1.2555 +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1.2556 + do { \
1.2557 + volatile OrigFn _orig = (orig); \
1.2558 + volatile unsigned long _argvec[3+3]; \
1.2559 + volatile unsigned long _res; \
1.2560 + /* _argvec[0] holds current r2 across the call */ \
1.2561 + _argvec[1] = (unsigned long)_orig.r2; \
1.2562 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2563 + _argvec[2+1] = (unsigned long)arg1; \
1.2564 + _argvec[2+2] = (unsigned long)arg2; \
1.2565 + _argvec[2+3] = (unsigned long)arg3; \
1.2566 + __asm__ volatile( \
1.2567 + "mr 11,%1\n\t" \
1.2568 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.2569 + "stw 2,-8(11)\n\t" /* save tocptr */ \
1.2570 + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
1.2571 + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
1.2572 + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
1.2573 + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
1.2574 + "lwz 11, 0(11)\n\t" /* target->r11 */ \
1.2575 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2576 + "mr 11,%1\n\t" \
1.2577 + "mr %0,3\n\t" \
1.2578 + "lwz 2,-8(11)\n\t" /* restore tocptr */ \
1.2579 + VG_CONTRACT_FRAME_BY(512) \
1.2580 + : /*out*/ "=r" (_res) \
1.2581 + : /*in*/ "r" (&_argvec[2]) \
1.2582 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2583 + ); \
1.2584 + lval = (__typeof__(lval)) _res; \
1.2585 + } while (0)
1.2586 +
1.2587 +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1.2588 + do { \
1.2589 + volatile OrigFn _orig = (orig); \
1.2590 + volatile unsigned long _argvec[3+4]; \
1.2591 + volatile unsigned long _res; \
1.2592 + /* _argvec[0] holds current r2 across the call */ \
1.2593 + _argvec[1] = (unsigned long)_orig.r2; \
1.2594 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2595 + _argvec[2+1] = (unsigned long)arg1; \
1.2596 + _argvec[2+2] = (unsigned long)arg2; \
1.2597 + _argvec[2+3] = (unsigned long)arg3; \
1.2598 + _argvec[2+4] = (unsigned long)arg4; \
1.2599 + __asm__ volatile( \
1.2600 + "mr 11,%1\n\t" \
1.2601 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.2602 + "stw 2,-8(11)\n\t" /* save tocptr */ \
1.2603 + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
1.2604 + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
1.2605 + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
1.2606 + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
1.2607 + "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
1.2608 + "lwz 11, 0(11)\n\t" /* target->r11 */ \
1.2609 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2610 + "mr 11,%1\n\t" \
1.2611 + "mr %0,3\n\t" \
1.2612 + "lwz 2,-8(11)\n\t" /* restore tocptr */ \
1.2613 + VG_CONTRACT_FRAME_BY(512) \
1.2614 + : /*out*/ "=r" (_res) \
1.2615 + : /*in*/ "r" (&_argvec[2]) \
1.2616 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2617 + ); \
1.2618 + lval = (__typeof__(lval)) _res; \
1.2619 + } while (0)
1.2620 +
1.2621 +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1.2622 + do { \
1.2623 + volatile OrigFn _orig = (orig); \
1.2624 + volatile unsigned long _argvec[3+5]; \
1.2625 + volatile unsigned long _res; \
1.2626 + /* _argvec[0] holds current r2 across the call */ \
1.2627 + _argvec[1] = (unsigned long)_orig.r2; \
1.2628 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2629 + _argvec[2+1] = (unsigned long)arg1; \
1.2630 + _argvec[2+2] = (unsigned long)arg2; \
1.2631 + _argvec[2+3] = (unsigned long)arg3; \
1.2632 + _argvec[2+4] = (unsigned long)arg4; \
1.2633 + _argvec[2+5] = (unsigned long)arg5; \
1.2634 + __asm__ volatile( \
1.2635 + "mr 11,%1\n\t" \
1.2636 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.2637 + "stw 2,-8(11)\n\t" /* save tocptr */ \
1.2638 + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
1.2639 + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
1.2640 + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
1.2641 + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
1.2642 + "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
1.2643 + "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
1.2644 + "lwz 11, 0(11)\n\t" /* target->r11 */ \
1.2645 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2646 + "mr 11,%1\n\t" \
1.2647 + "mr %0,3\n\t" \
1.2648 + "lwz 2,-8(11)\n\t" /* restore tocptr */ \
1.2649 + VG_CONTRACT_FRAME_BY(512) \
1.2650 + : /*out*/ "=r" (_res) \
1.2651 + : /*in*/ "r" (&_argvec[2]) \
1.2652 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2653 + ); \
1.2654 + lval = (__typeof__(lval)) _res; \
1.2655 + } while (0)
1.2656 +
1.2657 +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1.2658 + do { \
1.2659 + volatile OrigFn _orig = (orig); \
1.2660 + volatile unsigned long _argvec[3+6]; \
1.2661 + volatile unsigned long _res; \
1.2662 + /* _argvec[0] holds current r2 across the call */ \
1.2663 + _argvec[1] = (unsigned long)_orig.r2; \
1.2664 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2665 + _argvec[2+1] = (unsigned long)arg1; \
1.2666 + _argvec[2+2] = (unsigned long)arg2; \
1.2667 + _argvec[2+3] = (unsigned long)arg3; \
1.2668 + _argvec[2+4] = (unsigned long)arg4; \
1.2669 + _argvec[2+5] = (unsigned long)arg5; \
1.2670 + _argvec[2+6] = (unsigned long)arg6; \
1.2671 + __asm__ volatile( \
1.2672 + "mr 11,%1\n\t" \
1.2673 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.2674 + "stw 2,-8(11)\n\t" /* save tocptr */ \
1.2675 + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
1.2676 + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
1.2677 + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
1.2678 + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
1.2679 + "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
1.2680 + "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
1.2681 + "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
1.2682 + "lwz 11, 0(11)\n\t" /* target->r11 */ \
1.2683 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2684 + "mr 11,%1\n\t" \
1.2685 + "mr %0,3\n\t" \
1.2686 + "lwz 2,-8(11)\n\t" /* restore tocptr */ \
1.2687 + VG_CONTRACT_FRAME_BY(512) \
1.2688 + : /*out*/ "=r" (_res) \
1.2689 + : /*in*/ "r" (&_argvec[2]) \
1.2690 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2691 + ); \
1.2692 + lval = (__typeof__(lval)) _res; \
1.2693 + } while (0)
1.2694 +
1.2695 +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.2696 + arg7) \
1.2697 + do { \
1.2698 + volatile OrigFn _orig = (orig); \
1.2699 + volatile unsigned long _argvec[3+7]; \
1.2700 + volatile unsigned long _res; \
1.2701 + /* _argvec[0] holds current r2 across the call */ \
1.2702 + _argvec[1] = (unsigned long)_orig.r2; \
1.2703 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2704 + _argvec[2+1] = (unsigned long)arg1; \
1.2705 + _argvec[2+2] = (unsigned long)arg2; \
1.2706 + _argvec[2+3] = (unsigned long)arg3; \
1.2707 + _argvec[2+4] = (unsigned long)arg4; \
1.2708 + _argvec[2+5] = (unsigned long)arg5; \
1.2709 + _argvec[2+6] = (unsigned long)arg6; \
1.2710 + _argvec[2+7] = (unsigned long)arg7; \
1.2711 + __asm__ volatile( \
1.2712 + "mr 11,%1\n\t" \
1.2713 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.2714 + "stw 2,-8(11)\n\t" /* save tocptr */ \
1.2715 + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
1.2716 + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
1.2717 + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
1.2718 + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
1.2719 + "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
1.2720 + "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
1.2721 + "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
1.2722 + "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
1.2723 + "lwz 11, 0(11)\n\t" /* target->r11 */ \
1.2724 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2725 + "mr 11,%1\n\t" \
1.2726 + "mr %0,3\n\t" \
1.2727 + "lwz 2,-8(11)\n\t" /* restore tocptr */ \
1.2728 + VG_CONTRACT_FRAME_BY(512) \
1.2729 + : /*out*/ "=r" (_res) \
1.2730 + : /*in*/ "r" (&_argvec[2]) \
1.2731 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2732 + ); \
1.2733 + lval = (__typeof__(lval)) _res; \
1.2734 + } while (0)
1.2735 +
1.2736 +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.2737 + arg7,arg8) \
1.2738 + do { \
1.2739 + volatile OrigFn _orig = (orig); \
1.2740 + volatile unsigned long _argvec[3+8]; \
1.2741 + volatile unsigned long _res; \
1.2742 + /* _argvec[0] holds current r2 across the call */ \
1.2743 + _argvec[1] = (unsigned long)_orig.r2; \
1.2744 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2745 + _argvec[2+1] = (unsigned long)arg1; \
1.2746 + _argvec[2+2] = (unsigned long)arg2; \
1.2747 + _argvec[2+3] = (unsigned long)arg3; \
1.2748 + _argvec[2+4] = (unsigned long)arg4; \
1.2749 + _argvec[2+5] = (unsigned long)arg5; \
1.2750 + _argvec[2+6] = (unsigned long)arg6; \
1.2751 + _argvec[2+7] = (unsigned long)arg7; \
1.2752 + _argvec[2+8] = (unsigned long)arg8; \
1.2753 + __asm__ volatile( \
1.2754 + "mr 11,%1\n\t" \
1.2755 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.2756 + "stw 2,-8(11)\n\t" /* save tocptr */ \
1.2757 + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
1.2758 + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
1.2759 + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
1.2760 + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
1.2761 + "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
1.2762 + "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
1.2763 + "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
1.2764 + "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
1.2765 + "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
1.2766 + "lwz 11, 0(11)\n\t" /* target->r11 */ \
1.2767 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2768 + "mr 11,%1\n\t" \
1.2769 + "mr %0,3\n\t" \
1.2770 + "lwz 2,-8(11)\n\t" /* restore tocptr */ \
1.2771 + VG_CONTRACT_FRAME_BY(512) \
1.2772 + : /*out*/ "=r" (_res) \
1.2773 + : /*in*/ "r" (&_argvec[2]) \
1.2774 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2775 + ); \
1.2776 + lval = (__typeof__(lval)) _res; \
1.2777 + } while (0)
1.2778 +
1.2779 +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.2780 + arg7,arg8,arg9) \
1.2781 + do { \
1.2782 + volatile OrigFn _orig = (orig); \
1.2783 + volatile unsigned long _argvec[3+9]; \
1.2784 + volatile unsigned long _res; \
1.2785 + /* _argvec[0] holds current r2 across the call */ \
1.2786 + _argvec[1] = (unsigned long)_orig.r2; \
1.2787 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2788 + _argvec[2+1] = (unsigned long)arg1; \
1.2789 + _argvec[2+2] = (unsigned long)arg2; \
1.2790 + _argvec[2+3] = (unsigned long)arg3; \
1.2791 + _argvec[2+4] = (unsigned long)arg4; \
1.2792 + _argvec[2+5] = (unsigned long)arg5; \
1.2793 + _argvec[2+6] = (unsigned long)arg6; \
1.2794 + _argvec[2+7] = (unsigned long)arg7; \
1.2795 + _argvec[2+8] = (unsigned long)arg8; \
1.2796 + _argvec[2+9] = (unsigned long)arg9; \
1.2797 + __asm__ volatile( \
1.2798 + "mr 11,%1\n\t" \
1.2799 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.2800 + "stw 2,-8(11)\n\t" /* save tocptr */ \
1.2801 + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
1.2802 + VG_EXPAND_FRAME_BY_trashes_r3(64) \
1.2803 + /* arg9 */ \
1.2804 + "lwz 3,36(11)\n\t" \
1.2805 + "stw 3,56(1)\n\t" \
1.2806 + /* args1-8 */ \
1.2807 + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
1.2808 + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
1.2809 + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
1.2810 + "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
1.2811 + "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
1.2812 + "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
1.2813 + "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
1.2814 + "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
1.2815 + "lwz 11, 0(11)\n\t" /* target->r11 */ \
1.2816 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2817 + "mr 11,%1\n\t" \
1.2818 + "mr %0,3\n\t" \
1.2819 + "lwz 2,-8(11)\n\t" /* restore tocptr */ \
1.2820 + VG_CONTRACT_FRAME_BY(64) \
1.2821 + VG_CONTRACT_FRAME_BY(512) \
1.2822 + : /*out*/ "=r" (_res) \
1.2823 + : /*in*/ "r" (&_argvec[2]) \
1.2824 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2825 + ); \
1.2826 + lval = (__typeof__(lval)) _res; \
1.2827 + } while (0)
1.2828 +
1.2829 +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.2830 + arg7,arg8,arg9,arg10) \
1.2831 + do { \
1.2832 + volatile OrigFn _orig = (orig); \
1.2833 + volatile unsigned long _argvec[3+10]; \
1.2834 + volatile unsigned long _res; \
1.2835 + /* _argvec[0] holds current r2 across the call */ \
1.2836 + _argvec[1] = (unsigned long)_orig.r2; \
1.2837 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2838 + _argvec[2+1] = (unsigned long)arg1; \
1.2839 + _argvec[2+2] = (unsigned long)arg2; \
1.2840 + _argvec[2+3] = (unsigned long)arg3; \
1.2841 + _argvec[2+4] = (unsigned long)arg4; \
1.2842 + _argvec[2+5] = (unsigned long)arg5; \
1.2843 + _argvec[2+6] = (unsigned long)arg6; \
1.2844 + _argvec[2+7] = (unsigned long)arg7; \
1.2845 + _argvec[2+8] = (unsigned long)arg8; \
1.2846 + _argvec[2+9] = (unsigned long)arg9; \
1.2847 + _argvec[2+10] = (unsigned long)arg10; \
1.2848 + __asm__ volatile( \
1.2849 + "mr 11,%1\n\t" \
1.2850 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.2851 + "stw 2,-8(11)\n\t" /* save tocptr */ \
1.2852 + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
1.2853 + VG_EXPAND_FRAME_BY_trashes_r3(64) \
1.2854 + /* arg10 */ \
1.2855 + "lwz 3,40(11)\n\t" \
1.2856 + "stw 3,60(1)\n\t" \
1.2857 + /* arg9 */ \
1.2858 + "lwz 3,36(11)\n\t" \
1.2859 + "stw 3,56(1)\n\t" \
1.2860 + /* args1-8 */ \
1.2861 + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
1.2862 + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
1.2863 + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
1.2864 + "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
1.2865 + "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
1.2866 + "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
1.2867 + "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
1.2868 + "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
1.2869 + "lwz 11, 0(11)\n\t" /* target->r11 */ \
1.2870 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2871 + "mr 11,%1\n\t" \
1.2872 + "mr %0,3\n\t" \
1.2873 + "lwz 2,-8(11)\n\t" /* restore tocptr */ \
1.2874 + VG_CONTRACT_FRAME_BY(64) \
1.2875 + VG_CONTRACT_FRAME_BY(512) \
1.2876 + : /*out*/ "=r" (_res) \
1.2877 + : /*in*/ "r" (&_argvec[2]) \
1.2878 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2879 + ); \
1.2880 + lval = (__typeof__(lval)) _res; \
1.2881 + } while (0)
1.2882 +
1.2883 +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.2884 + arg7,arg8,arg9,arg10,arg11) \
1.2885 + do { \
1.2886 + volatile OrigFn _orig = (orig); \
1.2887 + volatile unsigned long _argvec[3+11]; \
1.2888 + volatile unsigned long _res; \
1.2889 + /* _argvec[0] holds current r2 across the call */ \
1.2890 + _argvec[1] = (unsigned long)_orig.r2; \
1.2891 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2892 + _argvec[2+1] = (unsigned long)arg1; \
1.2893 + _argvec[2+2] = (unsigned long)arg2; \
1.2894 + _argvec[2+3] = (unsigned long)arg3; \
1.2895 + _argvec[2+4] = (unsigned long)arg4; \
1.2896 + _argvec[2+5] = (unsigned long)arg5; \
1.2897 + _argvec[2+6] = (unsigned long)arg6; \
1.2898 + _argvec[2+7] = (unsigned long)arg7; \
1.2899 + _argvec[2+8] = (unsigned long)arg8; \
1.2900 + _argvec[2+9] = (unsigned long)arg9; \
1.2901 + _argvec[2+10] = (unsigned long)arg10; \
1.2902 + _argvec[2+11] = (unsigned long)arg11; \
1.2903 + __asm__ volatile( \
1.2904 + "mr 11,%1\n\t" \
1.2905 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.2906 + "stw 2,-8(11)\n\t" /* save tocptr */ \
1.2907 + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
1.2908 + VG_EXPAND_FRAME_BY_trashes_r3(72) \
1.2909 + /* arg11 */ \
1.2910 + "lwz 3,44(11)\n\t" \
1.2911 + "stw 3,64(1)\n\t" \
1.2912 + /* arg10 */ \
1.2913 + "lwz 3,40(11)\n\t" \
1.2914 + "stw 3,60(1)\n\t" \
1.2915 + /* arg9 */ \
1.2916 + "lwz 3,36(11)\n\t" \
1.2917 + "stw 3,56(1)\n\t" \
1.2918 + /* args1-8 */ \
1.2919 + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
1.2920 + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
1.2921 + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
1.2922 + "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
1.2923 + "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
1.2924 + "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
1.2925 + "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
1.2926 + "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
1.2927 + "lwz 11, 0(11)\n\t" /* target->r11 */ \
1.2928 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2929 + "mr 11,%1\n\t" \
1.2930 + "mr %0,3\n\t" \
1.2931 + "lwz 2,-8(11)\n\t" /* restore tocptr */ \
1.2932 + VG_CONTRACT_FRAME_BY(72) \
1.2933 + VG_CONTRACT_FRAME_BY(512) \
1.2934 + : /*out*/ "=r" (_res) \
1.2935 + : /*in*/ "r" (&_argvec[2]) \
1.2936 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2937 + ); \
1.2938 + lval = (__typeof__(lval)) _res; \
1.2939 + } while (0)
1.2940 +
1.2941 +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.2942 + arg7,arg8,arg9,arg10,arg11,arg12) \
1.2943 + do { \
1.2944 + volatile OrigFn _orig = (orig); \
1.2945 + volatile unsigned long _argvec[3+12]; \
1.2946 + volatile unsigned long _res; \
1.2947 + /* _argvec[0] holds current r2 across the call */ \
1.2948 + _argvec[1] = (unsigned long)_orig.r2; \
1.2949 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.2950 + _argvec[2+1] = (unsigned long)arg1; \
1.2951 + _argvec[2+2] = (unsigned long)arg2; \
1.2952 + _argvec[2+3] = (unsigned long)arg3; \
1.2953 + _argvec[2+4] = (unsigned long)arg4; \
1.2954 + _argvec[2+5] = (unsigned long)arg5; \
1.2955 + _argvec[2+6] = (unsigned long)arg6; \
1.2956 + _argvec[2+7] = (unsigned long)arg7; \
1.2957 + _argvec[2+8] = (unsigned long)arg8; \
1.2958 + _argvec[2+9] = (unsigned long)arg9; \
1.2959 + _argvec[2+10] = (unsigned long)arg10; \
1.2960 + _argvec[2+11] = (unsigned long)arg11; \
1.2961 + _argvec[2+12] = (unsigned long)arg12; \
1.2962 + __asm__ volatile( \
1.2963 + "mr 11,%1\n\t" \
1.2964 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.2965 + "stw 2,-8(11)\n\t" /* save tocptr */ \
1.2966 + "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
1.2967 + VG_EXPAND_FRAME_BY_trashes_r3(72) \
1.2968 + /* arg12 */ \
1.2969 + "lwz 3,48(11)\n\t" \
1.2970 + "stw 3,68(1)\n\t" \
1.2971 + /* arg11 */ \
1.2972 + "lwz 3,44(11)\n\t" \
1.2973 + "stw 3,64(1)\n\t" \
1.2974 + /* arg10 */ \
1.2975 + "lwz 3,40(11)\n\t" \
1.2976 + "stw 3,60(1)\n\t" \
1.2977 + /* arg9 */ \
1.2978 + "lwz 3,36(11)\n\t" \
1.2979 + "stw 3,56(1)\n\t" \
1.2980 + /* args1-8 */ \
1.2981 + "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
1.2982 + "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
1.2983 + "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
1.2984 + "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
1.2985 + "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
1.2986 + "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
1.2987 + "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
1.2988 + "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
1.2989 + "lwz 11, 0(11)\n\t" /* target->r11 */ \
1.2990 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.2991 + "mr 11,%1\n\t" \
1.2992 + "mr %0,3\n\t" \
1.2993 + "lwz 2,-8(11)\n\t" /* restore tocptr */ \
1.2994 + VG_CONTRACT_FRAME_BY(72) \
1.2995 + VG_CONTRACT_FRAME_BY(512) \
1.2996 + : /*out*/ "=r" (_res) \
1.2997 + : /*in*/ "r" (&_argvec[2]) \
1.2998 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.2999 + ); \
1.3000 + lval = (__typeof__(lval)) _res; \
1.3001 + } while (0)
1.3002 +
1.3003 +#endif /* PLAT_ppc32_aix5 */
1.3004 +
1.3005 +/* ------------------------ ppc64-aix5 ------------------------- */
1.3006 +
1.3007 +#if defined(PLAT_ppc64_aix5)
1.3008 +
1.3009 +/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
1.3010 +
1.3011 +/* These regs are trashed by the hidden call. */
1.3012 +#define __CALLER_SAVED_REGS \
1.3013 + "lr", "ctr", "xer", \
1.3014 + "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
1.3015 + "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
1.3016 + "r11", "r12", "r13"
1.3017 +
1.3018 +/* Expand the stack frame, copying enough info that unwinding
1.3019 + still works. Trashes r3. */
1.3020 +
1.3021 +#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
1.3022 + "addi 1,1,-" #_n_fr "\n\t" \
1.3023 + "ld 3," #_n_fr "(1)\n\t" \
1.3024 + "std 3,0(1)\n\t"
1.3025 +
1.3026 +#define VG_CONTRACT_FRAME_BY(_n_fr) \
1.3027 + "addi 1,1," #_n_fr "\n\t"
1.3028 +
1.3029 +/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
1.3030 + long) == 8. */
1.3031 +
1.3032 +#define CALL_FN_W_v(lval, orig) \
1.3033 + do { \
1.3034 + volatile OrigFn _orig = (orig); \
1.3035 + volatile unsigned long _argvec[3+0]; \
1.3036 + volatile unsigned long _res; \
1.3037 + /* _argvec[0] holds current r2 across the call */ \
1.3038 + _argvec[1] = (unsigned long)_orig.r2; \
1.3039 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.3040 + __asm__ volatile( \
1.3041 + "mr 11,%1\n\t" \
1.3042 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.3043 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.3044 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.3045 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.3046 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.3047 + "mr 11,%1\n\t" \
1.3048 + "mr %0,3\n\t" \
1.3049 + "ld 2,-16(11)\n\t" /* restore tocptr */ \
1.3050 + VG_CONTRACT_FRAME_BY(512) \
1.3051 + : /*out*/ "=r" (_res) \
1.3052 + : /*in*/ "r" (&_argvec[2]) \
1.3053 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.3054 + ); \
1.3055 + lval = (__typeof__(lval)) _res; \
1.3056 + } while (0)
1.3057 +
1.3058 +#define CALL_FN_W_W(lval, orig, arg1) \
1.3059 + do { \
1.3060 + volatile OrigFn _orig = (orig); \
1.3061 + volatile unsigned long _argvec[3+1]; \
1.3062 + volatile unsigned long _res; \
1.3063 + /* _argvec[0] holds current r2 across the call */ \
1.3064 + _argvec[1] = (unsigned long)_orig.r2; \
1.3065 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.3066 + _argvec[2+1] = (unsigned long)arg1; \
1.3067 + __asm__ volatile( \
1.3068 + "mr 11,%1\n\t" \
1.3069 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.3070 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.3071 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.3072 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.3073 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.3074 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.3075 + "mr 11,%1\n\t" \
1.3076 + "mr %0,3\n\t" \
1.3077 + "ld 2,-16(11)\n\t" /* restore tocptr */ \
1.3078 + VG_CONTRACT_FRAME_BY(512) \
1.3079 + : /*out*/ "=r" (_res) \
1.3080 + : /*in*/ "r" (&_argvec[2]) \
1.3081 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.3082 + ); \
1.3083 + lval = (__typeof__(lval)) _res; \
1.3084 + } while (0)
1.3085 +
1.3086 +#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
1.3087 + do { \
1.3088 + volatile OrigFn _orig = (orig); \
1.3089 + volatile unsigned long _argvec[3+2]; \
1.3090 + volatile unsigned long _res; \
1.3091 + /* _argvec[0] holds current r2 across the call */ \
1.3092 + _argvec[1] = (unsigned long)_orig.r2; \
1.3093 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.3094 + _argvec[2+1] = (unsigned long)arg1; \
1.3095 + _argvec[2+2] = (unsigned long)arg2; \
1.3096 + __asm__ volatile( \
1.3097 + "mr 11,%1\n\t" \
1.3098 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.3099 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.3100 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.3101 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.3102 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.3103 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.3104 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.3105 + "mr 11,%1\n\t" \
1.3106 + "mr %0,3\n\t" \
1.3107 + "ld 2,-16(11)\n\t" /* restore tocptr */ \
1.3108 + VG_CONTRACT_FRAME_BY(512) \
1.3109 + : /*out*/ "=r" (_res) \
1.3110 + : /*in*/ "r" (&_argvec[2]) \
1.3111 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.3112 + ); \
1.3113 + lval = (__typeof__(lval)) _res; \
1.3114 + } while (0)
1.3115 +
1.3116 +#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
1.3117 + do { \
1.3118 + volatile OrigFn _orig = (orig); \
1.3119 + volatile unsigned long _argvec[3+3]; \
1.3120 + volatile unsigned long _res; \
1.3121 + /* _argvec[0] holds current r2 across the call */ \
1.3122 + _argvec[1] = (unsigned long)_orig.r2; \
1.3123 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.3124 + _argvec[2+1] = (unsigned long)arg1; \
1.3125 + _argvec[2+2] = (unsigned long)arg2; \
1.3126 + _argvec[2+3] = (unsigned long)arg3; \
1.3127 + __asm__ volatile( \
1.3128 + "mr 11,%1\n\t" \
1.3129 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.3130 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.3131 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.3132 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.3133 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.3134 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.3135 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.3136 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.3137 + "mr 11,%1\n\t" \
1.3138 + "mr %0,3\n\t" \
1.3139 + "ld 2,-16(11)\n\t" /* restore tocptr */ \
1.3140 + VG_CONTRACT_FRAME_BY(512) \
1.3141 + : /*out*/ "=r" (_res) \
1.3142 + : /*in*/ "r" (&_argvec[2]) \
1.3143 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.3144 + ); \
1.3145 + lval = (__typeof__(lval)) _res; \
1.3146 + } while (0)
1.3147 +
1.3148 +#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
1.3149 + do { \
1.3150 + volatile OrigFn _orig = (orig); \
1.3151 + volatile unsigned long _argvec[3+4]; \
1.3152 + volatile unsigned long _res; \
1.3153 + /* _argvec[0] holds current r2 across the call */ \
1.3154 + _argvec[1] = (unsigned long)_orig.r2; \
1.3155 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.3156 + _argvec[2+1] = (unsigned long)arg1; \
1.3157 + _argvec[2+2] = (unsigned long)arg2; \
1.3158 + _argvec[2+3] = (unsigned long)arg3; \
1.3159 + _argvec[2+4] = (unsigned long)arg4; \
1.3160 + __asm__ volatile( \
1.3161 + "mr 11,%1\n\t" \
1.3162 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.3163 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.3164 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.3165 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.3166 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.3167 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.3168 + "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1.3169 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.3170 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.3171 + "mr 11,%1\n\t" \
1.3172 + "mr %0,3\n\t" \
1.3173 + "ld 2,-16(11)\n\t" /* restore tocptr */ \
1.3174 + VG_CONTRACT_FRAME_BY(512) \
1.3175 + : /*out*/ "=r" (_res) \
1.3176 + : /*in*/ "r" (&_argvec[2]) \
1.3177 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.3178 + ); \
1.3179 + lval = (__typeof__(lval)) _res; \
1.3180 + } while (0)
1.3181 +
1.3182 +#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
1.3183 + do { \
1.3184 + volatile OrigFn _orig = (orig); \
1.3185 + volatile unsigned long _argvec[3+5]; \
1.3186 + volatile unsigned long _res; \
1.3187 + /* _argvec[0] holds current r2 across the call */ \
1.3188 + _argvec[1] = (unsigned long)_orig.r2; \
1.3189 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.3190 + _argvec[2+1] = (unsigned long)arg1; \
1.3191 + _argvec[2+2] = (unsigned long)arg2; \
1.3192 + _argvec[2+3] = (unsigned long)arg3; \
1.3193 + _argvec[2+4] = (unsigned long)arg4; \
1.3194 + _argvec[2+5] = (unsigned long)arg5; \
1.3195 + __asm__ volatile( \
1.3196 + "mr 11,%1\n\t" \
1.3197 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.3198 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.3199 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.3200 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.3201 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.3202 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.3203 + "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1.3204 + "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1.3205 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.3206 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.3207 + "mr 11,%1\n\t" \
1.3208 + "mr %0,3\n\t" \
1.3209 + "ld 2,-16(11)\n\t" /* restore tocptr */ \
1.3210 + VG_CONTRACT_FRAME_BY(512) \
1.3211 + : /*out*/ "=r" (_res) \
1.3212 + : /*in*/ "r" (&_argvec[2]) \
1.3213 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.3214 + ); \
1.3215 + lval = (__typeof__(lval)) _res; \
1.3216 + } while (0)
1.3217 +
1.3218 +#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
1.3219 + do { \
1.3220 + volatile OrigFn _orig = (orig); \
1.3221 + volatile unsigned long _argvec[3+6]; \
1.3222 + volatile unsigned long _res; \
1.3223 + /* _argvec[0] holds current r2 across the call */ \
1.3224 + _argvec[1] = (unsigned long)_orig.r2; \
1.3225 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.3226 + _argvec[2+1] = (unsigned long)arg1; \
1.3227 + _argvec[2+2] = (unsigned long)arg2; \
1.3228 + _argvec[2+3] = (unsigned long)arg3; \
1.3229 + _argvec[2+4] = (unsigned long)arg4; \
1.3230 + _argvec[2+5] = (unsigned long)arg5; \
1.3231 + _argvec[2+6] = (unsigned long)arg6; \
1.3232 + __asm__ volatile( \
1.3233 + "mr 11,%1\n\t" \
1.3234 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.3235 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.3236 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.3237 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.3238 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.3239 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.3240 + "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1.3241 + "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1.3242 + "ld 8, 48(11)\n\t" /* arg6->r8 */ \
1.3243 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.3244 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.3245 + "mr 11,%1\n\t" \
1.3246 + "mr %0,3\n\t" \
1.3247 + "ld 2,-16(11)\n\t" /* restore tocptr */ \
1.3248 + VG_CONTRACT_FRAME_BY(512) \
1.3249 + : /*out*/ "=r" (_res) \
1.3250 + : /*in*/ "r" (&_argvec[2]) \
1.3251 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.3252 + ); \
1.3253 + lval = (__typeof__(lval)) _res; \
1.3254 + } while (0)
1.3255 +
1.3256 +#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.3257 + arg7) \
1.3258 + do { \
1.3259 + volatile OrigFn _orig = (orig); \
1.3260 + volatile unsigned long _argvec[3+7]; \
1.3261 + volatile unsigned long _res; \
1.3262 + /* _argvec[0] holds current r2 across the call */ \
1.3263 + _argvec[1] = (unsigned long)_orig.r2; \
1.3264 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.3265 + _argvec[2+1] = (unsigned long)arg1; \
1.3266 + _argvec[2+2] = (unsigned long)arg2; \
1.3267 + _argvec[2+3] = (unsigned long)arg3; \
1.3268 + _argvec[2+4] = (unsigned long)arg4; \
1.3269 + _argvec[2+5] = (unsigned long)arg5; \
1.3270 + _argvec[2+6] = (unsigned long)arg6; \
1.3271 + _argvec[2+7] = (unsigned long)arg7; \
1.3272 + __asm__ volatile( \
1.3273 + "mr 11,%1\n\t" \
1.3274 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.3275 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.3276 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.3277 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.3278 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.3279 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.3280 + "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1.3281 + "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1.3282 + "ld 8, 48(11)\n\t" /* arg6->r8 */ \
1.3283 + "ld 9, 56(11)\n\t" /* arg7->r9 */ \
1.3284 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.3285 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.3286 + "mr 11,%1\n\t" \
1.3287 + "mr %0,3\n\t" \
1.3288 + "ld 2,-16(11)\n\t" /* restore tocptr */ \
1.3289 + VG_CONTRACT_FRAME_BY(512) \
1.3290 + : /*out*/ "=r" (_res) \
1.3291 + : /*in*/ "r" (&_argvec[2]) \
1.3292 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.3293 + ); \
1.3294 + lval = (__typeof__(lval)) _res; \
1.3295 + } while (0)
1.3296 +
1.3297 +#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.3298 + arg7,arg8) \
1.3299 + do { \
1.3300 + volatile OrigFn _orig = (orig); \
1.3301 + volatile unsigned long _argvec[3+8]; \
1.3302 + volatile unsigned long _res; \
1.3303 + /* _argvec[0] holds current r2 across the call */ \
1.3304 + _argvec[1] = (unsigned long)_orig.r2; \
1.3305 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.3306 + _argvec[2+1] = (unsigned long)arg1; \
1.3307 + _argvec[2+2] = (unsigned long)arg2; \
1.3308 + _argvec[2+3] = (unsigned long)arg3; \
1.3309 + _argvec[2+4] = (unsigned long)arg4; \
1.3310 + _argvec[2+5] = (unsigned long)arg5; \
1.3311 + _argvec[2+6] = (unsigned long)arg6; \
1.3312 + _argvec[2+7] = (unsigned long)arg7; \
1.3313 + _argvec[2+8] = (unsigned long)arg8; \
1.3314 + __asm__ volatile( \
1.3315 + "mr 11,%1\n\t" \
1.3316 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.3317 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.3318 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.3319 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.3320 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.3321 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.3322 + "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1.3323 + "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1.3324 + "ld 8, 48(11)\n\t" /* arg6->r8 */ \
1.3325 + "ld 9, 56(11)\n\t" /* arg7->r9 */ \
1.3326 + "ld 10, 64(11)\n\t" /* arg8->r10 */ \
1.3327 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.3328 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.3329 + "mr 11,%1\n\t" \
1.3330 + "mr %0,3\n\t" \
1.3331 + "ld 2,-16(11)\n\t" /* restore tocptr */ \
1.3332 + VG_CONTRACT_FRAME_BY(512) \
1.3333 + : /*out*/ "=r" (_res) \
1.3334 + : /*in*/ "r" (&_argvec[2]) \
1.3335 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.3336 + ); \
1.3337 + lval = (__typeof__(lval)) _res; \
1.3338 + } while (0)
1.3339 +
1.3340 +#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.3341 + arg7,arg8,arg9) \
1.3342 + do { \
1.3343 + volatile OrigFn _orig = (orig); \
1.3344 + volatile unsigned long _argvec[3+9]; \
1.3345 + volatile unsigned long _res; \
1.3346 + /* _argvec[0] holds current r2 across the call */ \
1.3347 + _argvec[1] = (unsigned long)_orig.r2; \
1.3348 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.3349 + _argvec[2+1] = (unsigned long)arg1; \
1.3350 + _argvec[2+2] = (unsigned long)arg2; \
1.3351 + _argvec[2+3] = (unsigned long)arg3; \
1.3352 + _argvec[2+4] = (unsigned long)arg4; \
1.3353 + _argvec[2+5] = (unsigned long)arg5; \
1.3354 + _argvec[2+6] = (unsigned long)arg6; \
1.3355 + _argvec[2+7] = (unsigned long)arg7; \
1.3356 + _argvec[2+8] = (unsigned long)arg8; \
1.3357 + _argvec[2+9] = (unsigned long)arg9; \
1.3358 + __asm__ volatile( \
1.3359 + "mr 11,%1\n\t" \
1.3360 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.3361 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.3362 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.3363 + VG_EXPAND_FRAME_BY_trashes_r3(128) \
1.3364 + /* arg9 */ \
1.3365 + "ld 3,72(11)\n\t" \
1.3366 + "std 3,112(1)\n\t" \
1.3367 + /* args1-8 */ \
1.3368 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.3369 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.3370 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.3371 + "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1.3372 + "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1.3373 + "ld 8, 48(11)\n\t" /* arg6->r8 */ \
1.3374 + "ld 9, 56(11)\n\t" /* arg7->r9 */ \
1.3375 + "ld 10, 64(11)\n\t" /* arg8->r10 */ \
1.3376 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.3377 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.3378 + "mr 11,%1\n\t" \
1.3379 + "mr %0,3\n\t" \
1.3380 + "ld 2,-16(11)\n\t" /* restore tocptr */ \
1.3381 + VG_CONTRACT_FRAME_BY(128) \
1.3382 + VG_CONTRACT_FRAME_BY(512) \
1.3383 + : /*out*/ "=r" (_res) \
1.3384 + : /*in*/ "r" (&_argvec[2]) \
1.3385 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.3386 + ); \
1.3387 + lval = (__typeof__(lval)) _res; \
1.3388 + } while (0)
1.3389 +
1.3390 +#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.3391 + arg7,arg8,arg9,arg10) \
1.3392 + do { \
1.3393 + volatile OrigFn _orig = (orig); \
1.3394 + volatile unsigned long _argvec[3+10]; \
1.3395 + volatile unsigned long _res; \
1.3396 + /* _argvec[0] holds current r2 across the call */ \
1.3397 + _argvec[1] = (unsigned long)_orig.r2; \
1.3398 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.3399 + _argvec[2+1] = (unsigned long)arg1; \
1.3400 + _argvec[2+2] = (unsigned long)arg2; \
1.3401 + _argvec[2+3] = (unsigned long)arg3; \
1.3402 + _argvec[2+4] = (unsigned long)arg4; \
1.3403 + _argvec[2+5] = (unsigned long)arg5; \
1.3404 + _argvec[2+6] = (unsigned long)arg6; \
1.3405 + _argvec[2+7] = (unsigned long)arg7; \
1.3406 + _argvec[2+8] = (unsigned long)arg8; \
1.3407 + _argvec[2+9] = (unsigned long)arg9; \
1.3408 + _argvec[2+10] = (unsigned long)arg10; \
1.3409 + __asm__ volatile( \
1.3410 + "mr 11,%1\n\t" \
1.3411 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.3412 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.3413 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.3414 + VG_EXPAND_FRAME_BY_trashes_r3(128) \
1.3415 + /* arg10 */ \
1.3416 + "ld 3,80(11)\n\t" \
1.3417 + "std 3,120(1)\n\t" \
1.3418 + /* arg9 */ \
1.3419 + "ld 3,72(11)\n\t" \
1.3420 + "std 3,112(1)\n\t" \
1.3421 + /* args1-8 */ \
1.3422 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.3423 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.3424 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.3425 + "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1.3426 + "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1.3427 + "ld 8, 48(11)\n\t" /* arg6->r8 */ \
1.3428 + "ld 9, 56(11)\n\t" /* arg7->r9 */ \
1.3429 + "ld 10, 64(11)\n\t" /* arg8->r10 */ \
1.3430 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.3431 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.3432 + "mr 11,%1\n\t" \
1.3433 + "mr %0,3\n\t" \
1.3434 + "ld 2,-16(11)\n\t" /* restore tocptr */ \
1.3435 + VG_CONTRACT_FRAME_BY(128) \
1.3436 + VG_CONTRACT_FRAME_BY(512) \
1.3437 + : /*out*/ "=r" (_res) \
1.3438 + : /*in*/ "r" (&_argvec[2]) \
1.3439 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.3440 + ); \
1.3441 + lval = (__typeof__(lval)) _res; \
1.3442 + } while (0)
1.3443 +
1.3444 +#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.3445 + arg7,arg8,arg9,arg10,arg11) \
1.3446 + do { \
1.3447 + volatile OrigFn _orig = (orig); \
1.3448 + volatile unsigned long _argvec[3+11]; \
1.3449 + volatile unsigned long _res; \
1.3450 + /* _argvec[0] holds current r2 across the call */ \
1.3451 + _argvec[1] = (unsigned long)_orig.r2; \
1.3452 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.3453 + _argvec[2+1] = (unsigned long)arg1; \
1.3454 + _argvec[2+2] = (unsigned long)arg2; \
1.3455 + _argvec[2+3] = (unsigned long)arg3; \
1.3456 + _argvec[2+4] = (unsigned long)arg4; \
1.3457 + _argvec[2+5] = (unsigned long)arg5; \
1.3458 + _argvec[2+6] = (unsigned long)arg6; \
1.3459 + _argvec[2+7] = (unsigned long)arg7; \
1.3460 + _argvec[2+8] = (unsigned long)arg8; \
1.3461 + _argvec[2+9] = (unsigned long)arg9; \
1.3462 + _argvec[2+10] = (unsigned long)arg10; \
1.3463 + _argvec[2+11] = (unsigned long)arg11; \
1.3464 + __asm__ volatile( \
1.3465 + "mr 11,%1\n\t" \
1.3466 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.3467 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.3468 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.3469 + VG_EXPAND_FRAME_BY_trashes_r3(144) \
1.3470 + /* arg11 */ \
1.3471 + "ld 3,88(11)\n\t" \
1.3472 + "std 3,128(1)\n\t" \
1.3473 + /* arg10 */ \
1.3474 + "ld 3,80(11)\n\t" \
1.3475 + "std 3,120(1)\n\t" \
1.3476 + /* arg9 */ \
1.3477 + "ld 3,72(11)\n\t" \
1.3478 + "std 3,112(1)\n\t" \
1.3479 + /* args1-8 */ \
1.3480 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.3481 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.3482 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.3483 + "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1.3484 + "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1.3485 + "ld 8, 48(11)\n\t" /* arg6->r8 */ \
1.3486 + "ld 9, 56(11)\n\t" /* arg7->r9 */ \
1.3487 + "ld 10, 64(11)\n\t" /* arg8->r10 */ \
1.3488 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.3489 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.3490 + "mr 11,%1\n\t" \
1.3491 + "mr %0,3\n\t" \
1.3492 + "ld 2,-16(11)\n\t" /* restore tocptr */ \
1.3493 + VG_CONTRACT_FRAME_BY(144) \
1.3494 + VG_CONTRACT_FRAME_BY(512) \
1.3495 + : /*out*/ "=r" (_res) \
1.3496 + : /*in*/ "r" (&_argvec[2]) \
1.3497 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.3498 + ); \
1.3499 + lval = (__typeof__(lval)) _res; \
1.3500 + } while (0)
1.3501 +
1.3502 +#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
1.3503 + arg7,arg8,arg9,arg10,arg11,arg12) \
1.3504 + do { \
1.3505 + volatile OrigFn _orig = (orig); \
1.3506 + volatile unsigned long _argvec[3+12]; \
1.3507 + volatile unsigned long _res; \
1.3508 + /* _argvec[0] holds current r2 across the call */ \
1.3509 + _argvec[1] = (unsigned long)_orig.r2; \
1.3510 + _argvec[2] = (unsigned long)_orig.nraddr; \
1.3511 + _argvec[2+1] = (unsigned long)arg1; \
1.3512 + _argvec[2+2] = (unsigned long)arg2; \
1.3513 + _argvec[2+3] = (unsigned long)arg3; \
1.3514 + _argvec[2+4] = (unsigned long)arg4; \
1.3515 + _argvec[2+5] = (unsigned long)arg5; \
1.3516 + _argvec[2+6] = (unsigned long)arg6; \
1.3517 + _argvec[2+7] = (unsigned long)arg7; \
1.3518 + _argvec[2+8] = (unsigned long)arg8; \
1.3519 + _argvec[2+9] = (unsigned long)arg9; \
1.3520 + _argvec[2+10] = (unsigned long)arg10; \
1.3521 + _argvec[2+11] = (unsigned long)arg11; \
1.3522 + _argvec[2+12] = (unsigned long)arg12; \
1.3523 + __asm__ volatile( \
1.3524 + "mr 11,%1\n\t" \
1.3525 + VG_EXPAND_FRAME_BY_trashes_r3(512) \
1.3526 + "std 2,-16(11)\n\t" /* save tocptr */ \
1.3527 + "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
1.3528 + VG_EXPAND_FRAME_BY_trashes_r3(144) \
1.3529 + /* arg12 */ \
1.3530 + "ld 3,96(11)\n\t" \
1.3531 + "std 3,136(1)\n\t" \
1.3532 + /* arg11 */ \
1.3533 + "ld 3,88(11)\n\t" \
1.3534 + "std 3,128(1)\n\t" \
1.3535 + /* arg10 */ \
1.3536 + "ld 3,80(11)\n\t" \
1.3537 + "std 3,120(1)\n\t" \
1.3538 + /* arg9 */ \
1.3539 + "ld 3,72(11)\n\t" \
1.3540 + "std 3,112(1)\n\t" \
1.3541 + /* args1-8 */ \
1.3542 + "ld 3, 8(11)\n\t" /* arg1->r3 */ \
1.3543 + "ld 4, 16(11)\n\t" /* arg2->r4 */ \
1.3544 + "ld 5, 24(11)\n\t" /* arg3->r5 */ \
1.3545 + "ld 6, 32(11)\n\t" /* arg4->r6 */ \
1.3546 + "ld 7, 40(11)\n\t" /* arg5->r7 */ \
1.3547 + "ld 8, 48(11)\n\t" /* arg6->r8 */ \
1.3548 + "ld 9, 56(11)\n\t" /* arg7->r9 */ \
1.3549 + "ld 10, 64(11)\n\t" /* arg8->r10 */ \
1.3550 + "ld 11, 0(11)\n\t" /* target->r11 */ \
1.3551 + VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
1.3552 + "mr 11,%1\n\t" \
1.3553 + "mr %0,3\n\t" \
1.3554 + "ld 2,-16(11)\n\t" /* restore tocptr */ \
1.3555 + VG_CONTRACT_FRAME_BY(144) \
1.3556 + VG_CONTRACT_FRAME_BY(512) \
1.3557 + : /*out*/ "=r" (_res) \
1.3558 + : /*in*/ "r" (&_argvec[2]) \
1.3559 + : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
1.3560 + ); \
1.3561 + lval = (__typeof__(lval)) _res; \
1.3562 + } while (0)
1.3563 +
1.3564 +#endif /* PLAT_ppc64_aix5 */
1.3565 +
1.3566 +
1.3567 +/* ------------------------------------------------------------------ */
1.3568 +/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
1.3569 +/* */
1.3570 +/* ------------------------------------------------------------------ */
1.3571 +
1.3572 +/* Some request codes. There are many more of these, but most are not
1.3573 + exposed to end-user view. These are the public ones, all of the
1.3574 + form 0x1000 + small_number.
1.3575 +
1.3576 + Core ones are in the range 0x00000000--0x0000ffff. The non-public
1.3577 + ones start at 0x2000.
1.3578 +*/
1.3579 +
1.3580 +/* These macros are used by tools -- they must be public, but don't
1.3581 + embed them into other programs. */
1.3582 +#define VG_USERREQ_TOOL_BASE(a,b) \
1.3583 + ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
1.3584 +#define VG_IS_TOOL_USERREQ(a, b, v) \
1.3585 + (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
1.3586 +
1.3587 +/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
1.3588 + This enum comprises an ABI exported by Valgrind to programs
1.3589 + which use client requests. DO NOT CHANGE THE ORDER OF THESE
1.3590 + ENTRIES, NOR DELETE ANY -- add new ones at the end. */
1.3591 +typedef
1.3592 + enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
1.3593 + VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
1.3594 +
1.3595 + /* These allow any function to be called from the simulated
1.3596 + CPU but run on the real CPU. Nb: the first arg passed to
1.3597 + the function is always the ThreadId of the running
1.3598 + thread! So CLIENT_CALL0 actually requires a 1 arg
1.3599 + function, etc. */
1.3600 + VG_USERREQ__CLIENT_CALL0 = 0x1101,
1.3601 + VG_USERREQ__CLIENT_CALL1 = 0x1102,
1.3602 + VG_USERREQ__CLIENT_CALL2 = 0x1103,
1.3603 + VG_USERREQ__CLIENT_CALL3 = 0x1104,
1.3604 +
1.3605 + /* Can be useful in regression testing suites -- eg. can
1.3606 + send Valgrind's output to /dev/null and still count
1.3607 + errors. */
1.3608 + VG_USERREQ__COUNT_ERRORS = 0x1201,
1.3609 +
1.3610 + /* These are useful and can be interpreted by any tool that
1.3611 + tracks malloc() et al, by using vg_replace_malloc.c. */
1.3612 + VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
1.3613 + VG_USERREQ__FREELIKE_BLOCK = 0x1302,
1.3614 + /* Memory pool support. */
1.3615 + VG_USERREQ__CREATE_MEMPOOL = 0x1303,
1.3616 + VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
1.3617 + VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
1.3618 + VG_USERREQ__MEMPOOL_FREE = 0x1306,
1.3619 + VG_USERREQ__MEMPOOL_TRIM = 0x1307,
1.3620 + VG_USERREQ__MOVE_MEMPOOL = 0x1308,
1.3621 + VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
1.3622 + VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
1.3623 +
1.3624 + /* Allow printfs to valgrind log. */
1.3625 + VG_USERREQ__PRINTF = 0x1401,
1.3626 + VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
1.3627 +
1.3628 + /* Stack support. */
1.3629 + VG_USERREQ__STACK_REGISTER = 0x1501,
1.3630 + VG_USERREQ__STACK_DEREGISTER = 0x1502,
1.3631 + VG_USERREQ__STACK_CHANGE = 0x1503
1.3632 + } Vg_ClientRequest;
1.3633 +
1.3634 +#if !defined(__GNUC__)
1.3635 +# define __extension__ /* */
1.3636 +#endif
1.3637 +
1.3638 +/* Returns the number of Valgrinds this code is running under. That
1.3639 + is, 0 if running natively, 1 if running under Valgrind, 2 if
1.3640 + running under Valgrind which is running under another Valgrind,
1.3641 + etc. */
1.3642 +#define RUNNING_ON_VALGRIND __extension__ \
1.3643 + ({unsigned int _qzz_res; \
1.3644 + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \
1.3645 + VG_USERREQ__RUNNING_ON_VALGRIND, \
1.3646 + 0, 0, 0, 0, 0); \
1.3647 + _qzz_res; \
1.3648 + })
1.3649 +
1.3650 +
1.3651 +/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
1.3652 + _qzz_len - 1]. Useful if you are debugging a JITter or some such,
1.3653 + since it provides a way to make sure valgrind will retranslate the
1.3654 + invalidated area. Returns no value. */
1.3655 +#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
1.3656 + {unsigned int _qzz_res; \
1.3657 + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
1.3658 + VG_USERREQ__DISCARD_TRANSLATIONS, \
1.3659 + _qzz_addr, _qzz_len, 0, 0, 0); \
1.3660 + }
1.3661 +
1.3662 +
1.3663 +/* These requests are for getting Valgrind itself to print something.
1.3664 + Possibly with a backtrace. This is a really ugly hack. */
1.3665 +
1.3666 +#if defined(NVALGRIND)
1.3667 +
1.3668 +# define VALGRIND_PRINTF(...)
1.3669 +# define VALGRIND_PRINTF_BACKTRACE(...)
1.3670 +
1.3671 +#else /* NVALGRIND */
1.3672 +
1.3673 +/* Modern GCC will optimize the static routine out if unused,
1.3674 + and unused attribute will shut down warnings about it. */
1.3675 +static int VALGRIND_PRINTF(const char *format, ...)
1.3676 + __attribute__((format(__printf__, 1, 2), __unused__));
1.3677 +static int
1.3678 +VALGRIND_PRINTF(const char *format, ...)
1.3679 +{
1.3680 + unsigned long _qzz_res;
1.3681 + va_list vargs;
1.3682 + va_start(vargs, format);
1.3683 + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF,
1.3684 + (unsigned long)format, (unsigned long)vargs,
1.3685 + 0, 0, 0);
1.3686 + va_end(vargs);
1.3687 + return (int)_qzz_res;
1.3688 +}
1.3689 +
1.3690 +static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
1.3691 + __attribute__((format(__printf__, 1, 2), __unused__));
1.3692 +static int
1.3693 +VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
1.3694 +{
1.3695 + unsigned long _qzz_res;
1.3696 + va_list vargs;
1.3697 + va_start(vargs, format);
1.3698 + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE,
1.3699 + (unsigned long)format, (unsigned long)vargs,
1.3700 + 0, 0, 0);
1.3701 + va_end(vargs);
1.3702 + return (int)_qzz_res;
1.3703 +}
1.3704 +
1.3705 +#endif /* NVALGRIND */
1.3706 +
1.3707 +
1.3708 +/* These requests allow control to move from the simulated CPU to the
1.3709 + real CPU, calling an arbitary function.
1.3710 +
1.3711 + Note that the current ThreadId is inserted as the first argument.
1.3712 + So this call:
1.3713 +
1.3714 + VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
1.3715 +
1.3716 + requires f to have this signature:
1.3717 +
1.3718 + Word f(Word tid, Word arg1, Word arg2)
1.3719 +
1.3720 + where "Word" is a word-sized type.
1.3721 +
1.3722 + Note that these client requests are not entirely reliable. For example,
1.3723 + if you call a function with them that subsequently calls printf(),
1.3724 + there's a high chance Valgrind will crash. Generally, your prospects of
1.3725 + these working are made higher if the called function does not refer to
1.3726 + any global variables, and does not refer to any libc or other functions
1.3727 + (printf et al). Any kind of entanglement with libc or dynamic linking is
1.3728 + likely to have a bad outcome, for tricky reasons which we've grappled
1.3729 + with a lot in the past.
1.3730 +*/
1.3731 +#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
1.3732 + __extension__ \
1.3733 + ({unsigned long _qyy_res; \
1.3734 + VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
1.3735 + VG_USERREQ__CLIENT_CALL0, \
1.3736 + _qyy_fn, \
1.3737 + 0, 0, 0, 0); \
1.3738 + _qyy_res; \
1.3739 + })
1.3740 +
1.3741 +#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
1.3742 + __extension__ \
1.3743 + ({unsigned long _qyy_res; \
1.3744 + VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
1.3745 + VG_USERREQ__CLIENT_CALL1, \
1.3746 + _qyy_fn, \
1.3747 + _qyy_arg1, 0, 0, 0); \
1.3748 + _qyy_res; \
1.3749 + })
1.3750 +
1.3751 +#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
1.3752 + __extension__ \
1.3753 + ({unsigned long _qyy_res; \
1.3754 + VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
1.3755 + VG_USERREQ__CLIENT_CALL2, \
1.3756 + _qyy_fn, \
1.3757 + _qyy_arg1, _qyy_arg2, 0, 0); \
1.3758 + _qyy_res; \
1.3759 + })
1.3760 +
1.3761 +#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
1.3762 + __extension__ \
1.3763 + ({unsigned long _qyy_res; \
1.3764 + VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
1.3765 + VG_USERREQ__CLIENT_CALL3, \
1.3766 + _qyy_fn, \
1.3767 + _qyy_arg1, _qyy_arg2, \
1.3768 + _qyy_arg3, 0); \
1.3769 + _qyy_res; \
1.3770 + })
1.3771 +
1.3772 +
1.3773 +/* Counts the number of errors that have been recorded by a tool. Nb:
1.3774 + the tool must record the errors with VG_(maybe_record_error)() or
1.3775 + VG_(unique_error)() for them to be counted. */
1.3776 +#define VALGRIND_COUNT_ERRORS \
1.3777 + __extension__ \
1.3778 + ({unsigned int _qyy_res; \
1.3779 + VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
1.3780 + VG_USERREQ__COUNT_ERRORS, \
1.3781 + 0, 0, 0, 0, 0); \
1.3782 + _qyy_res; \
1.3783 + })
1.3784 +
1.3785 +/* Mark a block of memory as having been allocated by a malloc()-like
1.3786 + function. `addr' is the start of the usable block (ie. after any
1.3787 + redzone) `rzB' is redzone size if the allocator can apply redzones;
1.3788 + use '0' if not. Adding redzones makes it more likely Valgrind will spot
1.3789 + block overruns. `is_zeroed' indicates if the memory is zeroed, as it is
1.3790 + for calloc(). Put it immediately after the point where a block is
1.3791 + allocated.
1.3792 +
1.3793 + If you're using Memcheck: If you're allocating memory via superblocks,
1.3794 + and then handing out small chunks of each superblock, if you don't have
1.3795 + redzones on your small blocks, it's worth marking the superblock with
1.3796 + VALGRIND_MAKE_MEM_NOACCESS when it's created, so that block overruns are
1.3797 + detected. But if you can put redzones on, it's probably better to not do
1.3798 + this, so that messages for small overruns are described in terms of the
1.3799 + small block rather than the superblock (but if you have a big overrun
1.3800 + that skips over a redzone, you could miss an error this way). See
1.3801 + memcheck/tests/custom_alloc.c for an example.
1.3802 +
1.3803 + WARNING: if your allocator uses malloc() or 'new' to allocate
1.3804 + superblocks, rather than mmap() or brk(), this will not work properly --
1.3805 + you'll likely get assertion failures during leak detection. This is
1.3806 + because Valgrind doesn't like seeing overlapping heap blocks. Sorry.
1.3807 +
1.3808 + Nb: block must be freed via a free()-like function specified
1.3809 + with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */
1.3810 +#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
1.3811 + {unsigned int _qzz_res; \
1.3812 + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
1.3813 + VG_USERREQ__MALLOCLIKE_BLOCK, \
1.3814 + addr, sizeB, rzB, is_zeroed, 0); \
1.3815 + }
1.3816 +
1.3817 +/* Mark a block of memory as having been freed by a free()-like function.
1.3818 + `rzB' is redzone size; it must match that given to
1.3819 + VALGRIND_MALLOCLIKE_BLOCK. Memory not freed will be detected by the leak
1.3820 + checker. Put it immediately after the point where the block is freed. */
1.3821 +#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
1.3822 + {unsigned int _qzz_res; \
1.3823 + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
1.3824 + VG_USERREQ__FREELIKE_BLOCK, \
1.3825 + addr, rzB, 0, 0, 0); \
1.3826 + }
1.3827 +
1.3828 +/* Create a memory pool. */
1.3829 +#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
1.3830 + {unsigned int _qzz_res; \
1.3831 + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
1.3832 + VG_USERREQ__CREATE_MEMPOOL, \
1.3833 + pool, rzB, is_zeroed, 0, 0); \
1.3834 + }
1.3835 +
1.3836 +/* Destroy a memory pool. */
1.3837 +#define VALGRIND_DESTROY_MEMPOOL(pool) \
1.3838 + {unsigned int _qzz_res; \
1.3839 + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
1.3840 + VG_USERREQ__DESTROY_MEMPOOL, \
1.3841 + pool, 0, 0, 0, 0); \
1.3842 + }
1.3843 +
1.3844 +/* Associate a piece of memory with a memory pool. */
1.3845 +#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
1.3846 + {unsigned int _qzz_res; \
1.3847 + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
1.3848 + VG_USERREQ__MEMPOOL_ALLOC, \
1.3849 + pool, addr, size, 0, 0); \
1.3850 + }
1.3851 +
1.3852 +/* Disassociate a piece of memory from a memory pool. */
1.3853 +#define VALGRIND_MEMPOOL_FREE(pool, addr) \
1.3854 + {unsigned int _qzz_res; \
1.3855 + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
1.3856 + VG_USERREQ__MEMPOOL_FREE, \
1.3857 + pool, addr, 0, 0, 0); \
1.3858 + }
1.3859 +
1.3860 +/* Disassociate any pieces outside a particular range. */
1.3861 +#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
1.3862 + {unsigned int _qzz_res; \
1.3863 + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
1.3864 + VG_USERREQ__MEMPOOL_TRIM, \
1.3865 + pool, addr, size, 0, 0); \
1.3866 + }
1.3867 +
1.3868 +/* Resize and/or move a piece associated with a memory pool. */
1.3869 +#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
1.3870 + {unsigned int _qzz_res; \
1.3871 + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
1.3872 + VG_USERREQ__MOVE_MEMPOOL, \
1.3873 + poolA, poolB, 0, 0, 0); \
1.3874 + }
1.3875 +
1.3876 +/* Resize and/or move a piece associated with a memory pool. */
1.3877 +#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
1.3878 + {unsigned int _qzz_res; \
1.3879 + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
1.3880 + VG_USERREQ__MEMPOOL_CHANGE, \
1.3881 + pool, addrA, addrB, size, 0); \
1.3882 + }
1.3883 +
1.3884 +/* Return 1 if a mempool exists, else 0. */
1.3885 +#define VALGRIND_MEMPOOL_EXISTS(pool) \
1.3886 + ({unsigned int _qzz_res; \
1.3887 + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
1.3888 + VG_USERREQ__MEMPOOL_EXISTS, \
1.3889 + pool, 0, 0, 0, 0); \
1.3890 + _qzz_res; \
1.3891 + })
1.3892 +
1.3893 +/* Mark a piece of memory as being a stack. Returns a stack id. */
1.3894 +#define VALGRIND_STACK_REGISTER(start, end) \
1.3895 + ({unsigned int _qzz_res; \
1.3896 + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
1.3897 + VG_USERREQ__STACK_REGISTER, \
1.3898 + start, end, 0, 0, 0); \
1.3899 + _qzz_res; \
1.3900 + })
1.3901 +
1.3902 +/* Unmark the piece of memory associated with a stack id as being a
1.3903 + stack. */
1.3904 +#define VALGRIND_STACK_DEREGISTER(id) \
1.3905 + {unsigned int _qzz_res; \
1.3906 + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
1.3907 + VG_USERREQ__STACK_DEREGISTER, \
1.3908 + id, 0, 0, 0, 0); \
1.3909 + }
1.3910 +
1.3911 +/* Change the start and end address of the stack id. */
1.3912 +#define VALGRIND_STACK_CHANGE(id, start, end) \
1.3913 + {unsigned int _qzz_res; \
1.3914 + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
1.3915 + VG_USERREQ__STACK_CHANGE, \
1.3916 + id, start, end, 0, 0); \
1.3917 + }
1.3918 +
1.3919 +
1.3920 +#undef PLAT_x86_linux
1.3921 +#undef PLAT_amd64_linux
1.3922 +#undef PLAT_ppc32_linux
1.3923 +#undef PLAT_ppc64_linux
1.3924 +#undef PLAT_ppc32_aix5
1.3925 +#undef PLAT_ppc64_aix5
1.3926 +
1.3927 +#endif /* __VALGRIND_H */