valgrind.h revision c8259b85b701d25d72aabe9dc0a8154517f96913
181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* -*- c -*- 281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ---------------------------------------------------------------- 381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray Notice that the following BSD-style license applies to this one 581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray file (valgrind.h) only. The rest of Valgrind is licensed under the 681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray terms of the GNU General Public License, version 2, unless 781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray otherwise indicated. See the COPYING file in the source 881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray distribution for details. 981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 1081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ---------------------------------------------------------------- 1181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 1281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray This file is part of Valgrind, a dynamic binary instrumentation 1381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray framework. 1481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 1581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray Copyright (C) 2000-2009 Julian Seward. All rights reserved. 1681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 1781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray Redistribution and use in source and binary forms, with or without 1881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray modification, are permitted provided that the following conditions 1981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray are met: 2081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 2181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 1. Redistributions of source code must retain the above copyright 2281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray notice, this list of conditions and the following disclaimer. 2381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 2481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 2. The origin of this software must not be misrepresented; you must 2581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray not claim that you wrote the original software. If you use this 2681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray software in a product, an acknowledgment in the product 2781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray documentation would be appreciated but is not required. 2881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 2981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 3. Altered source versions must be plainly marked as such, and must 3081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray not be misrepresented as being the original software. 3181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 3281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 4. The name of the author may not be used to endorse or promote 3381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray products derived from this software without specific prior written 3481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray permission. 3581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 3681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 3781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 3881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 4081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 4281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 4381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 4481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 4581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 4681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 4781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 4881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ---------------------------------------------------------------- 4981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 5081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray Notice that the above BSD-style license applies to this one file 5181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray (valgrind.h) only. The entire rest of Valgrind is licensed under 5281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray the terms of the GNU General Public License, version 2. See the 5381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray COPYING file in the source distribution for details. 5481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 5581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ---------------------------------------------------------------- 5681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray*/ 5781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 5881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 5981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* This file is for inclusion into client (your!) code. 6081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 6181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray You can use these macros to manipulate and query Valgrind's 6281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray execution inside your own programs. 6381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 6481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray The resulting executables will still run without Valgrind, just a 6581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray little bit more slowly than they otherwise would, but otherwise 6681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray unchanged. When not running on valgrind, each client request 6781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray consumes very few (eg. 7) instructions, so the resulting performance 6881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray loss is negligible unless you plan to execute client requests 6981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray millions of times per second. Nevertheless, if that is still a 7081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray problem, you can compile with the NVALGRIND symbol defined (gcc 7181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray -DNVALGRIND) so that client requests are not even compiled in. */ 7281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 7381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#ifndef __VALGRIND_H 7481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define __VALGRIND_H 7581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 7681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#include <stdarg.h> 7781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 7881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* Nb: this file might be included in a file compiled with -ansi. So 7981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray we can't use C++ style "//" comments nor the "asm" keyword (instead 8081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray use "__asm__"). */ 8181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 8281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* Derive some tags indicating what the target platform is. Note 8381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray that in this file we're using the compiler's CPP symbols for 8481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray identifying architectures, which are different to the ones we use 8581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray within the rest of Valgrind. Note, __powerpc__ is active for both 8681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 32 and 64-bit PPC, whereas __powerpc64__ is only active for the 8781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray latter (on Linux, that is). */ 8881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#undef PLAT_x86_linux 8981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#undef PLAT_amd64_linux 9081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#undef PLAT_ppc32_linux 9181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#undef PLAT_ppc64_linux 9281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#undef PLAT_ppc32_aix5 9381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#undef PLAT_ppc64_aix5 9481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 9581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if !defined(_AIX) && defined(__i386__) 9681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray# define PLAT_x86_linux 1 9781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#elif !defined(_AIX) && defined(__x86_64__) 9881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray# define PLAT_amd64_linux 1 9981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__) 10081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray# define PLAT_ppc32_linux 1 10181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__) 10281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray# define PLAT_ppc64_linux 1 10381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#elif defined(_AIX) && defined(__64BIT__) 10481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray# define PLAT_ppc64_aix5 1 10581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#elif defined(_AIX) && !defined(__64BIT__) 10681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray# define PLAT_ppc32_aix5 1 10781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#endif 10881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 10981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 11081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* If we're not compiling for our target platform, don't generate 11181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray any inline asms. */ 11281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if !defined(PLAT_x86_linux) && !defined(PLAT_amd64_linux) \ 11381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray && !defined(PLAT_ppc32_linux) && !defined(PLAT_ppc64_linux) \ 11481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray && !defined(PLAT_ppc32_aix5) && !defined(PLAT_ppc64_aix5) 11581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray# if !defined(NVALGRIND) 11681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray# define NVALGRIND 1 11781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray# endif 11881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#endif 11981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 12081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 12181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------------------------------------------------ */ 12281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */ 12381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* in here of use to end-users -- skip to the next section. */ 12481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------------------------------------------------ */ 12581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 12681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if defined(NVALGRIND) 12781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 12881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* Define NVALGRIND to completely remove the Valgrind magic sequence 12981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray from the compiled code (analogous to NDEBUG's effects on 13081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray assert()) */ 13181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_DO_CLIENT_REQUEST( \ 13281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_rlval, _zzq_default, _zzq_request, \ 13381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 13481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray { \ 13581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray (_zzq_rlval) = (_zzq_default); \ 13681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 13781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 13881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#else /* ! NVALGRIND */ 13981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 14081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* The following defines the magic code sequences which the JITter 14181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray spots and handles magically. Don't look too closely at them as 14281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray they will rot your brain. 14381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 14481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray The assembly code sequences for all architectures is in this one 14581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray file. This is because this file must be stand-alone, and we don't 14681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray want to have multiple files. 14781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 14881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default 14981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray value gets put in the return slot, so that everything works when 15081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray this is executed not under Valgrind. Args are passed in a memory 15181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray block, and so there's no intrinsic limit to the number that could 15281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray be passed, but it's currently five. 15381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 15481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray The macro args are: 15581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_rlval result lvalue 15681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_default default value (result returned when running on real CPU) 15781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_request request code 15881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_arg1..5 request params 15981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 16081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray The other two macros are used to support function wrapping, and are 16181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the 16281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray guest's NRADDR pseudo-register and whatever other information is 16381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray needed to safely run the call original from the wrapper: on 16481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ppc64-linux, the R2 value at the divert point is also needed. This 16581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray information is abstracted into a user-visible type, OrigFn. 16681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 16781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray VALGRIND_CALL_NOREDIR_* behaves the same as the following on the 16881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray guest, but guarantees that the branch instruction will not be 16981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64: 17081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a 17181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray complete inline asm, since it needs to be combined with more magic 17281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray inline asm stuff to be useful. 17381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray*/ 17481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 17581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------- x86-linux ------------------------- */ 17681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 17781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if defined(PLAT_x86_linux) 17881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 17981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murraytypedef 18081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray struct { 18181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray unsigned int nraddr; /* where's the code? */ 18281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 18381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray OrigFn; 18481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 18581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define __SPECIAL_INSTRUCTION_PREAMBLE \ 18681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "roll $3, %%edi ; roll $13, %%edi\n\t" \ 18781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "roll $29, %%edi ; roll $19, %%edi\n\t" 18881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 18981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_DO_CLIENT_REQUEST( \ 19081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_rlval, _zzq_default, _zzq_request, \ 19181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 19281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray { volatile unsigned int _zzq_args[6]; \ 19381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned int _zzq_result; \ 19481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[0] = (unsigned int)(_zzq_request); \ 19581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[1] = (unsigned int)(_zzq_arg1); \ 19681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[2] = (unsigned int)(_zzq_arg2); \ 19781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[3] = (unsigned int)(_zzq_arg3); \ 19881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[4] = (unsigned int)(_zzq_arg4); \ 19981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[5] = (unsigned int)(_zzq_arg5); \ 20081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 20181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* %EDX = client_request ( %EAX ) */ \ 20281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "xchgl %%ebx,%%ebx" \ 20381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "=d" (_zzq_result) \ 20481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "a" (&_zzq_args[0]), "0" (_zzq_default) \ 20581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "cc", "memory" \ 20681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ); \ 20781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_rlval = _zzq_result; \ 20881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 20981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 21081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 21181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 21281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned int __addr; \ 21381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 21481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* %EAX = guest_NRADDR */ \ 21581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "xchgl %%ecx,%%ecx" \ 21681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "=a" (__addr) \ 21781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : \ 21881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "cc", "memory" \ 21981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ); \ 22081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_orig->nraddr = __addr; \ 22181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 22281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 22381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_CALL_NOREDIR_EAX \ 22481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __SPECIAL_INSTRUCTION_PREAMBLE \ 22581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* call-noredir *%EAX */ \ 22681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "xchgl %%edx,%%edx\n\t" 22781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#endif /* PLAT_x86_linux */ 22881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 22981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------ amd64-linux ------------------------ */ 23081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 23181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if defined(PLAT_amd64_linux) 23281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 23381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murraytypedef 23481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray struct { 23581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray unsigned long long int nraddr; /* where's the code? */ 23681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 23781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray OrigFn; 23881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 23981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define __SPECIAL_INSTRUCTION_PREAMBLE \ 24081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \ 24181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" 24281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 24381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_DO_CLIENT_REQUEST( \ 24481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_rlval, _zzq_default, _zzq_request, \ 24581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 24681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray { volatile unsigned long long int _zzq_args[6]; \ 24781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned long long int _zzq_result; \ 24881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[0] = (unsigned long long int)(_zzq_request); \ 24981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ 25081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ 25181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ 25281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ 25381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ 25481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 25581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* %RDX = client_request ( %RAX ) */ \ 25681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "xchgq %%rbx,%%rbx" \ 25781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "=d" (_zzq_result) \ 25881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "a" (&_zzq_args[0]), "0" (_zzq_default) \ 25981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "cc", "memory" \ 26081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ); \ 26181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_rlval = _zzq_result; \ 26281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 26381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 26481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 26581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 26681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned long long int __addr; \ 26781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 26881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* %RAX = guest_NRADDR */ \ 26981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "xchgq %%rcx,%%rcx" \ 27081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "=a" (__addr) \ 27181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : \ 27281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "cc", "memory" \ 27381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ); \ 27481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_orig->nraddr = __addr; \ 27581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 27681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 27781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_CALL_NOREDIR_RAX \ 27881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __SPECIAL_INSTRUCTION_PREAMBLE \ 27981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* call-noredir *%RAX */ \ 28081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "xchgq %%rdx,%%rdx\n\t" 28181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#endif /* PLAT_amd64_linux */ 28281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 28381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------ ppc32-linux ------------------------ */ 28481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 28581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if defined(PLAT_ppc32_linux) 28681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 28781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murraytypedef 28881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray struct { 28981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray unsigned int nraddr; /* where's the code? */ 29081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 29181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray OrigFn; 29281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 29381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define __SPECIAL_INSTRUCTION_PREAMBLE \ 29481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ 29581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" 29681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 29781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_DO_CLIENT_REQUEST( \ 29881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_rlval, _zzq_default, _zzq_request, \ 29981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 30081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray \ 30181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray { unsigned int _zzq_args[6]; \ 30281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray unsigned int _zzq_result; \ 30381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray unsigned int* _zzq_ptr; \ 30481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[0] = (unsigned int)(_zzq_request); \ 30581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[1] = (unsigned int)(_zzq_arg1); \ 30681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[2] = (unsigned int)(_zzq_arg2); \ 30781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[3] = (unsigned int)(_zzq_arg3); \ 30881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[4] = (unsigned int)(_zzq_arg4); \ 30981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[5] = (unsigned int)(_zzq_arg5); \ 31081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_ptr = _zzq_args; \ 31181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile("mr 3,%1\n\t" /*default*/ \ 31281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "mr 4,%2\n\t" /*ptr*/ \ 31381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __SPECIAL_INSTRUCTION_PREAMBLE \ 31481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* %R3 = client_request ( %R4 ) */ \ 31581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "or 1,1,1\n\t" \ 31681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "mr %0,3" /*result*/ \ 31781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "=b" (_zzq_result) \ 31881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "b" (_zzq_default), "b" (_zzq_ptr) \ 31981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "cc", "memory", "r3", "r4"); \ 32081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_rlval = _zzq_result; \ 32181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 32281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 32381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 32481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 32581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray unsigned int __addr; \ 32681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 32781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* %R3 = guest_NRADDR */ \ 32881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "or 2,2,2\n\t" \ 32981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "mr %0,3" \ 33081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "=b" (__addr) \ 33181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : \ 33281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "cc", "memory", "r3" \ 33381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ); \ 33481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_orig->nraddr = __addr; \ 33581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 33681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 33781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 33881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __SPECIAL_INSTRUCTION_PREAMBLE \ 33981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* branch-and-link-to-noredir *%R11 */ \ 34081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "or 3,3,3\n\t" 34181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#endif /* PLAT_ppc32_linux */ 34281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 34381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------ ppc64-linux ------------------------ */ 34481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 34581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if defined(PLAT_ppc64_linux) 34681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 34781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murraytypedef 34881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray struct { 34981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray unsigned long long int nraddr; /* where's the code? */ 35081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray unsigned long long int r2; /* what tocptr do we need? */ 35181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 35281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray OrigFn; 35381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 35481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define __SPECIAL_INSTRUCTION_PREAMBLE \ 35581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ 35681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "rotldi 0,0,61 ; rotldi 0,0,51\n\t" 35781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 35881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_DO_CLIENT_REQUEST( \ 35981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_rlval, _zzq_default, _zzq_request, \ 36081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 36181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray \ 36281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray { unsigned long long int _zzq_args[6]; \ 36381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray register unsigned long long int _zzq_result __asm__("r3"); \ 36481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray register unsigned long long int* _zzq_ptr __asm__("r4"); \ 36581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[0] = (unsigned long long int)(_zzq_request); \ 36681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ 36781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ 36881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ 36981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ 37081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ 37181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_ptr = _zzq_args; \ 37281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 37381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* %R3 = client_request ( %R4 ) */ \ 37481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "or 1,1,1" \ 37581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "=r" (_zzq_result) \ 37681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "0" (_zzq_default), "r" (_zzq_ptr) \ 37781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "cc", "memory"); \ 37881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_rlval = _zzq_result; \ 37981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 38081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 38181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 38281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 38381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray register unsigned long long int __addr __asm__("r3"); \ 38481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 38581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* %R3 = guest_NRADDR */ \ 38681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "or 2,2,2" \ 38781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "=r" (__addr) \ 38881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : \ 38981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "cc", "memory" \ 39081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ); \ 39181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_orig->nraddr = __addr; \ 39281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 39381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* %R3 = guest_NRADDR_GPR2 */ \ 39481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "or 4,4,4" \ 39581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "=r" (__addr) \ 39681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : \ 39781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "cc", "memory" \ 39881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ); \ 39981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_orig->r2 = __addr; \ 40081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 40181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 40281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 40381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __SPECIAL_INSTRUCTION_PREAMBLE \ 40481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* branch-and-link-to-noredir *%R11 */ \ 40581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "or 3,3,3\n\t" 40681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 40781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#endif /* PLAT_ppc64_linux */ 40881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 40981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------ ppc32-aix5 ------------------------- */ 41081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 41181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if defined(PLAT_ppc32_aix5) 41281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 41381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murraytypedef 41481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray struct { 41581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray unsigned int nraddr; /* where's the code? */ 41681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray unsigned int r2; /* what tocptr do we need? */ 41781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 41881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray OrigFn; 41981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 42081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define __SPECIAL_INSTRUCTION_PREAMBLE \ 42181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ 42281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" 42381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 42481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_DO_CLIENT_REQUEST( \ 42581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_rlval, _zzq_default, _zzq_request, \ 42681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 42781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray \ 42881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray { unsigned int _zzq_args[7]; \ 42981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray register unsigned int _zzq_result; \ 43081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray register unsigned int* _zzq_ptr; \ 43181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[0] = (unsigned int)(_zzq_request); \ 43281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[1] = (unsigned int)(_zzq_arg1); \ 43381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[2] = (unsigned int)(_zzq_arg2); \ 43481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[3] = (unsigned int)(_zzq_arg3); \ 43581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[4] = (unsigned int)(_zzq_arg4); \ 43681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[5] = (unsigned int)(_zzq_arg5); \ 43781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[6] = (unsigned int)(_zzq_default); \ 43881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_ptr = _zzq_args; \ 43981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile("mr 4,%1\n\t" \ 44081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "lwz 3, 24(4)\n\t" \ 44181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __SPECIAL_INSTRUCTION_PREAMBLE \ 44281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* %R3 = client_request ( %R4 ) */ \ 44381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "or 1,1,1\n\t" \ 44481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "mr %0,3" \ 44581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "=b" (_zzq_result) \ 44681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "b" (_zzq_ptr) \ 44781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "r3", "r4", "cc", "memory"); \ 44881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_rlval = _zzq_result; \ 44981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 45081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 45181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 45281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 45381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray register unsigned int __addr; \ 45481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 45581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* %R3 = guest_NRADDR */ \ 45681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "or 2,2,2\n\t" \ 45781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "mr %0,3" \ 45881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "=b" (__addr) \ 45981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : \ 46081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "r3", "cc", "memory" \ 46181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ); \ 46281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_orig->nraddr = __addr; \ 46381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 46481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* %R3 = guest_NRADDR_GPR2 */ \ 46581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "or 4,4,4\n\t" \ 46681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "mr %0,3" \ 46781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "=b" (__addr) \ 46881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : \ 46981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "r3", "cc", "memory" \ 47081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ); \ 47181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_orig->r2 = __addr; \ 47281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 47381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 47481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 47581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __SPECIAL_INSTRUCTION_PREAMBLE \ 47681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* branch-and-link-to-noredir *%R11 */ \ 47781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "or 3,3,3\n\t" 47881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 47981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#endif /* PLAT_ppc32_aix5 */ 48081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 48181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------ ppc64-aix5 ------------------------- */ 48281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 48381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if defined(PLAT_ppc64_aix5) 48481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 48581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murraytypedef 48681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray struct { 48781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray unsigned long long int nraddr; /* where's the code? */ 48881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray unsigned long long int r2; /* what tocptr do we need? */ 48981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 49081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray OrigFn; 49181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 49281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define __SPECIAL_INSTRUCTION_PREAMBLE \ 49381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ 49481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "rotldi 0,0,61 ; rotldi 0,0,51\n\t" 49581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 49681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_DO_CLIENT_REQUEST( \ 49781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_rlval, _zzq_default, _zzq_request, \ 49881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 49981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray \ 50081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray { unsigned long long int _zzq_args[7]; \ 50181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray register unsigned long long int _zzq_result; \ 50281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray register unsigned long long int* _zzq_ptr; \ 50381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[0] = (unsigned int long long)(_zzq_request); \ 50481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \ 50581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \ 50681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \ 50781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \ 50881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \ 50981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_args[6] = (unsigned int long long)(_zzq_default); \ 51081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_ptr = _zzq_args; \ 51181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile("mr 4,%1\n\t" \ 51281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "ld 3, 48(4)\n\t" \ 51381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __SPECIAL_INSTRUCTION_PREAMBLE \ 51481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* %R3 = client_request ( %R4 ) */ \ 51581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "or 1,1,1\n\t" \ 51681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "mr %0,3" \ 51781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "=b" (_zzq_result) \ 51881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "b" (_zzq_ptr) \ 51981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "r3", "r4", "cc", "memory"); \ 52081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_rlval = _zzq_result; \ 52181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 52281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 52381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 52481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 52581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray register unsigned long long int __addr; \ 52681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 52781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* %R3 = guest_NRADDR */ \ 52881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "or 2,2,2\n\t" \ 52981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "mr %0,3" \ 53081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "=b" (__addr) \ 53181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : \ 53281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "r3", "cc", "memory" \ 53381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ); \ 53481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_orig->nraddr = __addr; \ 53581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 53681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* %R3 = guest_NRADDR_GPR2 */ \ 53781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "or 4,4,4\n\t" \ 53881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "mr %0,3" \ 53981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "=b" (__addr) \ 54081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : \ 54181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : "r3", "cc", "memory" \ 54281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ); \ 54381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _zzq_orig->r2 = __addr; \ 54481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } 54581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 54681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 54781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __SPECIAL_INSTRUCTION_PREAMBLE \ 54881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray /* branch-and-link-to-noredir *%R11 */ \ 54981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "or 3,3,3\n\t" 55081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 55181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#endif /* PLAT_ppc64_aix5 */ 55281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 55381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* Insert assembly code for other platforms here... */ 55481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 55581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#endif /* NVALGRIND */ 55681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 55781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 55881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------------------------------------------------ */ 55981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */ 56081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ugly. It's the least-worst tradeoff I can think of. */ 56181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------------------------------------------------ */ 56281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 56381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* This section defines magic (a.k.a appalling-hack) macros for doing 56481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray guaranteed-no-redirection macros, so as to get from function 56581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray wrappers to the functions they are wrapping. The whole point is to 56681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray construct standard call sequences, but to do the call itself with a 56781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray special no-redirect call pseudo-instruction that the JIT 56881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray understands and handles specially. This section is long and 56981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray repetitious, and I can't see a way to make it shorter. 57081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 57181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray The naming scheme is as follows: 57281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 57381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc} 57481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 57581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 'W' stands for "word" and 'v' for "void". Hence there are 57681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray different macros for calling arity 0, 1, 2, 3, 4, etc, functions, 57781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray and for each, the possibility of returning a word-typed result, or 57881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray no result. 57981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray*/ 58081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 58181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* Use these to write the name of your wrapper. NOTE: duplicates 58281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */ 58381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 58481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \ 58581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _vgwZU_##soname##_##fnname 58681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 58781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \ 58881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _vgwZZ_##soname##_##fnname 58981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 59081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* Use this macro from within a wrapper function to collect the 59181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray context (address and possibly other info) of the original function. 59281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray Once you have that you can then use it in one of the CALL_FN_ 59381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray macros. The type of the argument _lval is OrigFn. */ 59481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval) 59581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 59681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* Derivatives of the main macros below, for calling functions 59781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray returning void. */ 59881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 59981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_v_v(fnptr) \ 60081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray do { volatile unsigned long _junk; \ 60181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray CALL_FN_W_v(_junk,fnptr); } while (0) 60281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 60381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_v_W(fnptr, arg1) \ 60481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray do { volatile unsigned long _junk; \ 60581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray CALL_FN_W_W(_junk,fnptr,arg1); } while (0) 60681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 60781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_v_WW(fnptr, arg1,arg2) \ 60881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray do { volatile unsigned long _junk; \ 60981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0) 61081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 61181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \ 61281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray do { volatile unsigned long _junk; \ 61381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0) 61481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 61581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* ------------------------- x86-linux ------------------------- */ 61681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 61781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#if defined(PLAT_x86_linux) 61881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 61981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* These regs are trashed by the hidden call. No need to mention eax 62081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray as gcc can already see that, plus causes gcc to bomb. */ 62181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx" 62281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 62381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned 62481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray long) == 4. */ 62581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 62681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_W_v(lval, orig) \ 62781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray do { \ 62881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile OrigFn _orig = (orig); \ 62981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned long _argvec[1]; \ 63081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned long _res; \ 63181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[0] = (unsigned long)_orig.nraddr; \ 63281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile( \ 63381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 63481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray VALGRIND_CALL_NOREDIR_EAX \ 63581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*out*/ "=a" (_res) \ 63681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*in*/ "a" (&_argvec[0]) \ 63781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 63881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ); \ 63981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray lval = (__typeof__(lval)) _res; \ 64081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } while (0) 64181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 64281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_W_W(lval, orig, arg1) \ 64381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray do { \ 64481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile OrigFn _orig = (orig); \ 64581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned long _argvec[2]; \ 64681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned long _res; \ 64781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[0] = (unsigned long)_orig.nraddr; \ 64881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[1] = (unsigned long)(arg1); \ 64981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile( \ 65081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 4(%%eax)\n\t" \ 65181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 65281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray VALGRIND_CALL_NOREDIR_EAX \ 65381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "addl $4, %%esp\n" \ 65481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*out*/ "=a" (_res) \ 65581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*in*/ "a" (&_argvec[0]) \ 65681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 65781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ); \ 65881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray lval = (__typeof__(lval)) _res; \ 65981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } while (0) 66081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 66181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 66281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray do { \ 66381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile OrigFn _orig = (orig); \ 66481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned long _argvec[3]; \ 66581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned long _res; \ 66681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[0] = (unsigned long)_orig.nraddr; \ 66781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[1] = (unsigned long)(arg1); \ 66881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[2] = (unsigned long)(arg2); \ 66981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile( \ 67081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 8(%%eax)\n\t" \ 67181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 4(%%eax)\n\t" \ 67281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 67381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray VALGRIND_CALL_NOREDIR_EAX \ 67481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "addl $8, %%esp\n" \ 67581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*out*/ "=a" (_res) \ 67681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*in*/ "a" (&_argvec[0]) \ 67781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 67881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ); \ 67981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray lval = (__typeof__(lval)) _res; \ 68081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } while (0) 68181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 68281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 68381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray do { \ 68481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile OrigFn _orig = (orig); \ 68581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned long _argvec[4]; \ 68681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned long _res; \ 68781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[0] = (unsigned long)_orig.nraddr; \ 68881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[1] = (unsigned long)(arg1); \ 68981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[2] = (unsigned long)(arg2); \ 69081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[3] = (unsigned long)(arg3); \ 69181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile( \ 69281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 12(%%eax)\n\t" \ 69381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 8(%%eax)\n\t" \ 69481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 4(%%eax)\n\t" \ 69581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 69681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray VALGRIND_CALL_NOREDIR_EAX \ 69781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "addl $12, %%esp\n" \ 69881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*out*/ "=a" (_res) \ 69981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*in*/ "a" (&_argvec[0]) \ 70081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 70181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ); \ 70281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray lval = (__typeof__(lval)) _res; \ 70381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } while (0) 70481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 70581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 70681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray do { \ 70781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile OrigFn _orig = (orig); \ 70881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned long _argvec[5]; \ 70981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned long _res; \ 71081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[0] = (unsigned long)_orig.nraddr; \ 71181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[1] = (unsigned long)(arg1); \ 71281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[2] = (unsigned long)(arg2); \ 71381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[3] = (unsigned long)(arg3); \ 71481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[4] = (unsigned long)(arg4); \ 71581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile( \ 71681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 16(%%eax)\n\t" \ 71781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 12(%%eax)\n\t" \ 71881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 8(%%eax)\n\t" \ 71981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 4(%%eax)\n\t" \ 72081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 72181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray VALGRIND_CALL_NOREDIR_EAX \ 72281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "addl $16, %%esp\n" \ 72381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*out*/ "=a" (_res) \ 72481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*in*/ "a" (&_argvec[0]) \ 72581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 72681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ); \ 72781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray lval = (__typeof__(lval)) _res; \ 72881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } while (0) 72981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 73081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 73181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray do { \ 73281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile OrigFn _orig = (orig); \ 73381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned long _argvec[6]; \ 73481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned long _res; \ 73581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[0] = (unsigned long)_orig.nraddr; \ 73681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[1] = (unsigned long)(arg1); \ 73781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[2] = (unsigned long)(arg2); \ 73881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[3] = (unsigned long)(arg3); \ 73981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[4] = (unsigned long)(arg4); \ 74081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[5] = (unsigned long)(arg5); \ 74181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile( \ 74281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 20(%%eax)\n\t" \ 74381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 16(%%eax)\n\t" \ 74481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 12(%%eax)\n\t" \ 74581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 8(%%eax)\n\t" \ 74681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 4(%%eax)\n\t" \ 74781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 74881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray VALGRIND_CALL_NOREDIR_EAX \ 74981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "addl $20, %%esp\n" \ 75081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*out*/ "=a" (_res) \ 75181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*in*/ "a" (&_argvec[0]) \ 75281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 75381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ); \ 75481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray lval = (__typeof__(lval)) _res; \ 75581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } while (0) 75681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 75781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 75881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray do { \ 75981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile OrigFn _orig = (orig); \ 76081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned long _argvec[7]; \ 76181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned long _res; \ 76281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[0] = (unsigned long)_orig.nraddr; \ 76381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[1] = (unsigned long)(arg1); \ 76481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[2] = (unsigned long)(arg2); \ 76581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[3] = (unsigned long)(arg3); \ 76681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[4] = (unsigned long)(arg4); \ 76781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[5] = (unsigned long)(arg5); \ 76881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[6] = (unsigned long)(arg6); \ 76981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile( \ 77081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 24(%%eax)\n\t" \ 77181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 20(%%eax)\n\t" \ 77281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 16(%%eax)\n\t" \ 77381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 12(%%eax)\n\t" \ 77481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 8(%%eax)\n\t" \ 77581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 4(%%eax)\n\t" \ 77681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 77781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray VALGRIND_CALL_NOREDIR_EAX \ 77881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "addl $24, %%esp\n" \ 77981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*out*/ "=a" (_res) \ 78081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*in*/ "a" (&_argvec[0]) \ 78181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 78281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray ); \ 78381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray lval = (__typeof__(lval)) _res; \ 78481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray } while (0) 78581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray 78681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 78781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray arg7) \ 78881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray do { \ 78981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile OrigFn _orig = (orig); \ 79081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned long _argvec[8]; \ 79181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray volatile unsigned long _res; \ 79281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[0] = (unsigned long)_orig.nraddr; \ 79381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[1] = (unsigned long)(arg1); \ 79481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[2] = (unsigned long)(arg2); \ 79581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[3] = (unsigned long)(arg3); \ 79681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[4] = (unsigned long)(arg4); \ 79781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[5] = (unsigned long)(arg5); \ 79881253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[6] = (unsigned long)(arg6); \ 79981253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray _argvec[7] = (unsigned long)(arg7); \ 80081253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray __asm__ volatile( \ 80181253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 28(%%eax)\n\t" \ 80281253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 24(%%eax)\n\t" \ 80381253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 20(%%eax)\n\t" \ 80481253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 16(%%eax)\n\t" \ 80581253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 12(%%eax)\n\t" \ 80681253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 8(%%eax)\n\t" \ 80781253e9afbc34b99e9adc22ddf33a1bfac56c697Tim Murray "pushl 4(%%eax)\n\t" \ 808 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 809 VALGRIND_CALL_NOREDIR_EAX \ 810 "addl $28, %%esp\n" \ 811 : /*out*/ "=a" (_res) \ 812 : /*in*/ "a" (&_argvec[0]) \ 813 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 814 ); \ 815 lval = (__typeof__(lval)) _res; \ 816 } while (0) 817 818#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 819 arg7,arg8) \ 820 do { \ 821 volatile OrigFn _orig = (orig); \ 822 volatile unsigned long _argvec[9]; \ 823 volatile unsigned long _res; \ 824 _argvec[0] = (unsigned long)_orig.nraddr; \ 825 _argvec[1] = (unsigned long)(arg1); \ 826 _argvec[2] = (unsigned long)(arg2); \ 827 _argvec[3] = (unsigned long)(arg3); \ 828 _argvec[4] = (unsigned long)(arg4); \ 829 _argvec[5] = (unsigned long)(arg5); \ 830 _argvec[6] = (unsigned long)(arg6); \ 831 _argvec[7] = (unsigned long)(arg7); \ 832 _argvec[8] = (unsigned long)(arg8); \ 833 __asm__ volatile( \ 834 "pushl 32(%%eax)\n\t" \ 835 "pushl 28(%%eax)\n\t" \ 836 "pushl 24(%%eax)\n\t" \ 837 "pushl 20(%%eax)\n\t" \ 838 "pushl 16(%%eax)\n\t" \ 839 "pushl 12(%%eax)\n\t" \ 840 "pushl 8(%%eax)\n\t" \ 841 "pushl 4(%%eax)\n\t" \ 842 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 843 VALGRIND_CALL_NOREDIR_EAX \ 844 "addl $32, %%esp\n" \ 845 : /*out*/ "=a" (_res) \ 846 : /*in*/ "a" (&_argvec[0]) \ 847 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 848 ); \ 849 lval = (__typeof__(lval)) _res; \ 850 } while (0) 851 852#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 853 arg7,arg8,arg9) \ 854 do { \ 855 volatile OrigFn _orig = (orig); \ 856 volatile unsigned long _argvec[10]; \ 857 volatile unsigned long _res; \ 858 _argvec[0] = (unsigned long)_orig.nraddr; \ 859 _argvec[1] = (unsigned long)(arg1); \ 860 _argvec[2] = (unsigned long)(arg2); \ 861 _argvec[3] = (unsigned long)(arg3); \ 862 _argvec[4] = (unsigned long)(arg4); \ 863 _argvec[5] = (unsigned long)(arg5); \ 864 _argvec[6] = (unsigned long)(arg6); \ 865 _argvec[7] = (unsigned long)(arg7); \ 866 _argvec[8] = (unsigned long)(arg8); \ 867 _argvec[9] = (unsigned long)(arg9); \ 868 __asm__ volatile( \ 869 "pushl 36(%%eax)\n\t" \ 870 "pushl 32(%%eax)\n\t" \ 871 "pushl 28(%%eax)\n\t" \ 872 "pushl 24(%%eax)\n\t" \ 873 "pushl 20(%%eax)\n\t" \ 874 "pushl 16(%%eax)\n\t" \ 875 "pushl 12(%%eax)\n\t" \ 876 "pushl 8(%%eax)\n\t" \ 877 "pushl 4(%%eax)\n\t" \ 878 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 879 VALGRIND_CALL_NOREDIR_EAX \ 880 "addl $36, %%esp\n" \ 881 : /*out*/ "=a" (_res) \ 882 : /*in*/ "a" (&_argvec[0]) \ 883 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 884 ); \ 885 lval = (__typeof__(lval)) _res; \ 886 } while (0) 887 888#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 889 arg7,arg8,arg9,arg10) \ 890 do { \ 891 volatile OrigFn _orig = (orig); \ 892 volatile unsigned long _argvec[11]; \ 893 volatile unsigned long _res; \ 894 _argvec[0] = (unsigned long)_orig.nraddr; \ 895 _argvec[1] = (unsigned long)(arg1); \ 896 _argvec[2] = (unsigned long)(arg2); \ 897 _argvec[3] = (unsigned long)(arg3); \ 898 _argvec[4] = (unsigned long)(arg4); \ 899 _argvec[5] = (unsigned long)(arg5); \ 900 _argvec[6] = (unsigned long)(arg6); \ 901 _argvec[7] = (unsigned long)(arg7); \ 902 _argvec[8] = (unsigned long)(arg8); \ 903 _argvec[9] = (unsigned long)(arg9); \ 904 _argvec[10] = (unsigned long)(arg10); \ 905 __asm__ volatile( \ 906 "pushl 40(%%eax)\n\t" \ 907 "pushl 36(%%eax)\n\t" \ 908 "pushl 32(%%eax)\n\t" \ 909 "pushl 28(%%eax)\n\t" \ 910 "pushl 24(%%eax)\n\t" \ 911 "pushl 20(%%eax)\n\t" \ 912 "pushl 16(%%eax)\n\t" \ 913 "pushl 12(%%eax)\n\t" \ 914 "pushl 8(%%eax)\n\t" \ 915 "pushl 4(%%eax)\n\t" \ 916 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 917 VALGRIND_CALL_NOREDIR_EAX \ 918 "addl $40, %%esp\n" \ 919 : /*out*/ "=a" (_res) \ 920 : /*in*/ "a" (&_argvec[0]) \ 921 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 922 ); \ 923 lval = (__typeof__(lval)) _res; \ 924 } while (0) 925 926#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ 927 arg6,arg7,arg8,arg9,arg10, \ 928 arg11) \ 929 do { \ 930 volatile OrigFn _orig = (orig); \ 931 volatile unsigned long _argvec[12]; \ 932 volatile unsigned long _res; \ 933 _argvec[0] = (unsigned long)_orig.nraddr; \ 934 _argvec[1] = (unsigned long)(arg1); \ 935 _argvec[2] = (unsigned long)(arg2); \ 936 _argvec[3] = (unsigned long)(arg3); \ 937 _argvec[4] = (unsigned long)(arg4); \ 938 _argvec[5] = (unsigned long)(arg5); \ 939 _argvec[6] = (unsigned long)(arg6); \ 940 _argvec[7] = (unsigned long)(arg7); \ 941 _argvec[8] = (unsigned long)(arg8); \ 942 _argvec[9] = (unsigned long)(arg9); \ 943 _argvec[10] = (unsigned long)(arg10); \ 944 _argvec[11] = (unsigned long)(arg11); \ 945 __asm__ volatile( \ 946 "pushl 44(%%eax)\n\t" \ 947 "pushl 40(%%eax)\n\t" \ 948 "pushl 36(%%eax)\n\t" \ 949 "pushl 32(%%eax)\n\t" \ 950 "pushl 28(%%eax)\n\t" \ 951 "pushl 24(%%eax)\n\t" \ 952 "pushl 20(%%eax)\n\t" \ 953 "pushl 16(%%eax)\n\t" \ 954 "pushl 12(%%eax)\n\t" \ 955 "pushl 8(%%eax)\n\t" \ 956 "pushl 4(%%eax)\n\t" \ 957 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 958 VALGRIND_CALL_NOREDIR_EAX \ 959 "addl $44, %%esp\n" \ 960 : /*out*/ "=a" (_res) \ 961 : /*in*/ "a" (&_argvec[0]) \ 962 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 963 ); \ 964 lval = (__typeof__(lval)) _res; \ 965 } while (0) 966 967#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ 968 arg6,arg7,arg8,arg9,arg10, \ 969 arg11,arg12) \ 970 do { \ 971 volatile OrigFn _orig = (orig); \ 972 volatile unsigned long _argvec[13]; \ 973 volatile unsigned long _res; \ 974 _argvec[0] = (unsigned long)_orig.nraddr; \ 975 _argvec[1] = (unsigned long)(arg1); \ 976 _argvec[2] = (unsigned long)(arg2); \ 977 _argvec[3] = (unsigned long)(arg3); \ 978 _argvec[4] = (unsigned long)(arg4); \ 979 _argvec[5] = (unsigned long)(arg5); \ 980 _argvec[6] = (unsigned long)(arg6); \ 981 _argvec[7] = (unsigned long)(arg7); \ 982 _argvec[8] = (unsigned long)(arg8); \ 983 _argvec[9] = (unsigned long)(arg9); \ 984 _argvec[10] = (unsigned long)(arg10); \ 985 _argvec[11] = (unsigned long)(arg11); \ 986 _argvec[12] = (unsigned long)(arg12); \ 987 __asm__ volatile( \ 988 "pushl 48(%%eax)\n\t" \ 989 "pushl 44(%%eax)\n\t" \ 990 "pushl 40(%%eax)\n\t" \ 991 "pushl 36(%%eax)\n\t" \ 992 "pushl 32(%%eax)\n\t" \ 993 "pushl 28(%%eax)\n\t" \ 994 "pushl 24(%%eax)\n\t" \ 995 "pushl 20(%%eax)\n\t" \ 996 "pushl 16(%%eax)\n\t" \ 997 "pushl 12(%%eax)\n\t" \ 998 "pushl 8(%%eax)\n\t" \ 999 "pushl 4(%%eax)\n\t" \ 1000 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1001 VALGRIND_CALL_NOREDIR_EAX \ 1002 "addl $48, %%esp\n" \ 1003 : /*out*/ "=a" (_res) \ 1004 : /*in*/ "a" (&_argvec[0]) \ 1005 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1006 ); \ 1007 lval = (__typeof__(lval)) _res; \ 1008 } while (0) 1009 1010#endif /* PLAT_x86_linux */ 1011 1012/* ------------------------ amd64-linux ------------------------ */ 1013 1014#if defined(PLAT_amd64_linux) 1015 1016/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */ 1017 1018/* These regs are trashed by the hidden call. */ 1019#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \ 1020 "rdi", "r8", "r9", "r10", "r11" 1021 1022/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned 1023 long) == 8. */ 1024 1025/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_ 1026 macros. In order not to trash the stack redzone, we need to drop 1027 %rsp by 128 before the hidden call, and restore afterwards. The 1028 nastyness is that it is only by luck that the stack still appears 1029 to be unwindable during the hidden call - since then the behaviour 1030 of any routine using this macro does not match what the CFI data 1031 says. Sigh. 1032 1033 Why is this important? Imagine that a wrapper has a stack 1034 allocated local, and passes to the hidden call, a pointer to it. 1035 Because gcc does not know about the hidden call, it may allocate 1036 that local in the redzone. Unfortunately the hidden call may then 1037 trash it before it comes to use it. So we must step clear of the 1038 redzone, for the duration of the hidden call, to make it safe. 1039 1040 Probably the same problem afflicts the other redzone-style ABIs too 1041 (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is 1042 self describing (none of this CFI nonsense) so at least messing 1043 with the stack pointer doesn't give a danger of non-unwindable 1044 stack. */ 1045 1046#define CALL_FN_W_v(lval, orig) \ 1047 do { \ 1048 volatile OrigFn _orig = (orig); \ 1049 volatile unsigned long _argvec[1]; \ 1050 volatile unsigned long _res; \ 1051 _argvec[0] = (unsigned long)_orig.nraddr; \ 1052 __asm__ volatile( \ 1053 "subq $128,%%rsp\n\t" \ 1054 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1055 VALGRIND_CALL_NOREDIR_RAX \ 1056 "addq $128,%%rsp\n\t" \ 1057 : /*out*/ "=a" (_res) \ 1058 : /*in*/ "a" (&_argvec[0]) \ 1059 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1060 ); \ 1061 lval = (__typeof__(lval)) _res; \ 1062 } while (0) 1063 1064#define CALL_FN_W_W(lval, orig, arg1) \ 1065 do { \ 1066 volatile OrigFn _orig = (orig); \ 1067 volatile unsigned long _argvec[2]; \ 1068 volatile unsigned long _res; \ 1069 _argvec[0] = (unsigned long)_orig.nraddr; \ 1070 _argvec[1] = (unsigned long)(arg1); \ 1071 __asm__ volatile( \ 1072 "subq $128,%%rsp\n\t" \ 1073 "movq 8(%%rax), %%rdi\n\t" \ 1074 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1075 VALGRIND_CALL_NOREDIR_RAX \ 1076 "addq $128,%%rsp\n\t" \ 1077 : /*out*/ "=a" (_res) \ 1078 : /*in*/ "a" (&_argvec[0]) \ 1079 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1080 ); \ 1081 lval = (__typeof__(lval)) _res; \ 1082 } while (0) 1083 1084#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 1085 do { \ 1086 volatile OrigFn _orig = (orig); \ 1087 volatile unsigned long _argvec[3]; \ 1088 volatile unsigned long _res; \ 1089 _argvec[0] = (unsigned long)_orig.nraddr; \ 1090 _argvec[1] = (unsigned long)(arg1); \ 1091 _argvec[2] = (unsigned long)(arg2); \ 1092 __asm__ volatile( \ 1093 "subq $128,%%rsp\n\t" \ 1094 "movq 16(%%rax), %%rsi\n\t" \ 1095 "movq 8(%%rax), %%rdi\n\t" \ 1096 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1097 VALGRIND_CALL_NOREDIR_RAX \ 1098 "addq $128,%%rsp\n\t" \ 1099 : /*out*/ "=a" (_res) \ 1100 : /*in*/ "a" (&_argvec[0]) \ 1101 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1102 ); \ 1103 lval = (__typeof__(lval)) _res; \ 1104 } while (0) 1105 1106#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 1107 do { \ 1108 volatile OrigFn _orig = (orig); \ 1109 volatile unsigned long _argvec[4]; \ 1110 volatile unsigned long _res; \ 1111 _argvec[0] = (unsigned long)_orig.nraddr; \ 1112 _argvec[1] = (unsigned long)(arg1); \ 1113 _argvec[2] = (unsigned long)(arg2); \ 1114 _argvec[3] = (unsigned long)(arg3); \ 1115 __asm__ volatile( \ 1116 "subq $128,%%rsp\n\t" \ 1117 "movq 24(%%rax), %%rdx\n\t" \ 1118 "movq 16(%%rax), %%rsi\n\t" \ 1119 "movq 8(%%rax), %%rdi\n\t" \ 1120 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1121 VALGRIND_CALL_NOREDIR_RAX \ 1122 "addq $128,%%rsp\n\t" \ 1123 : /*out*/ "=a" (_res) \ 1124 : /*in*/ "a" (&_argvec[0]) \ 1125 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1126 ); \ 1127 lval = (__typeof__(lval)) _res; \ 1128 } while (0) 1129 1130#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 1131 do { \ 1132 volatile OrigFn _orig = (orig); \ 1133 volatile unsigned long _argvec[5]; \ 1134 volatile unsigned long _res; \ 1135 _argvec[0] = (unsigned long)_orig.nraddr; \ 1136 _argvec[1] = (unsigned long)(arg1); \ 1137 _argvec[2] = (unsigned long)(arg2); \ 1138 _argvec[3] = (unsigned long)(arg3); \ 1139 _argvec[4] = (unsigned long)(arg4); \ 1140 __asm__ volatile( \ 1141 "subq $128,%%rsp\n\t" \ 1142 "movq 32(%%rax), %%rcx\n\t" \ 1143 "movq 24(%%rax), %%rdx\n\t" \ 1144 "movq 16(%%rax), %%rsi\n\t" \ 1145 "movq 8(%%rax), %%rdi\n\t" \ 1146 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1147 VALGRIND_CALL_NOREDIR_RAX \ 1148 "addq $128,%%rsp\n\t" \ 1149 : /*out*/ "=a" (_res) \ 1150 : /*in*/ "a" (&_argvec[0]) \ 1151 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1152 ); \ 1153 lval = (__typeof__(lval)) _res; \ 1154 } while (0) 1155 1156#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 1157 do { \ 1158 volatile OrigFn _orig = (orig); \ 1159 volatile unsigned long _argvec[6]; \ 1160 volatile unsigned long _res; \ 1161 _argvec[0] = (unsigned long)_orig.nraddr; \ 1162 _argvec[1] = (unsigned long)(arg1); \ 1163 _argvec[2] = (unsigned long)(arg2); \ 1164 _argvec[3] = (unsigned long)(arg3); \ 1165 _argvec[4] = (unsigned long)(arg4); \ 1166 _argvec[5] = (unsigned long)(arg5); \ 1167 __asm__ volatile( \ 1168 "subq $128,%%rsp\n\t" \ 1169 "movq 40(%%rax), %%r8\n\t" \ 1170 "movq 32(%%rax), %%rcx\n\t" \ 1171 "movq 24(%%rax), %%rdx\n\t" \ 1172 "movq 16(%%rax), %%rsi\n\t" \ 1173 "movq 8(%%rax), %%rdi\n\t" \ 1174 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1175 VALGRIND_CALL_NOREDIR_RAX \ 1176 "addq $128,%%rsp\n\t" \ 1177 : /*out*/ "=a" (_res) \ 1178 : /*in*/ "a" (&_argvec[0]) \ 1179 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1180 ); \ 1181 lval = (__typeof__(lval)) _res; \ 1182 } while (0) 1183 1184#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 1185 do { \ 1186 volatile OrigFn _orig = (orig); \ 1187 volatile unsigned long _argvec[7]; \ 1188 volatile unsigned long _res; \ 1189 _argvec[0] = (unsigned long)_orig.nraddr; \ 1190 _argvec[1] = (unsigned long)(arg1); \ 1191 _argvec[2] = (unsigned long)(arg2); \ 1192 _argvec[3] = (unsigned long)(arg3); \ 1193 _argvec[4] = (unsigned long)(arg4); \ 1194 _argvec[5] = (unsigned long)(arg5); \ 1195 _argvec[6] = (unsigned long)(arg6); \ 1196 __asm__ volatile( \ 1197 "subq $128,%%rsp\n\t" \ 1198 "movq 48(%%rax), %%r9\n\t" \ 1199 "movq 40(%%rax), %%r8\n\t" \ 1200 "movq 32(%%rax), %%rcx\n\t" \ 1201 "movq 24(%%rax), %%rdx\n\t" \ 1202 "movq 16(%%rax), %%rsi\n\t" \ 1203 "movq 8(%%rax), %%rdi\n\t" \ 1204 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1205 "addq $128,%%rsp\n\t" \ 1206 VALGRIND_CALL_NOREDIR_RAX \ 1207 : /*out*/ "=a" (_res) \ 1208 : /*in*/ "a" (&_argvec[0]) \ 1209 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1210 ); \ 1211 lval = (__typeof__(lval)) _res; \ 1212 } while (0) 1213 1214#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1215 arg7) \ 1216 do { \ 1217 volatile OrigFn _orig = (orig); \ 1218 volatile unsigned long _argvec[8]; \ 1219 volatile unsigned long _res; \ 1220 _argvec[0] = (unsigned long)_orig.nraddr; \ 1221 _argvec[1] = (unsigned long)(arg1); \ 1222 _argvec[2] = (unsigned long)(arg2); \ 1223 _argvec[3] = (unsigned long)(arg3); \ 1224 _argvec[4] = (unsigned long)(arg4); \ 1225 _argvec[5] = (unsigned long)(arg5); \ 1226 _argvec[6] = (unsigned long)(arg6); \ 1227 _argvec[7] = (unsigned long)(arg7); \ 1228 __asm__ volatile( \ 1229 "subq $128,%%rsp\n\t" \ 1230 "pushq 56(%%rax)\n\t" \ 1231 "movq 48(%%rax), %%r9\n\t" \ 1232 "movq 40(%%rax), %%r8\n\t" \ 1233 "movq 32(%%rax), %%rcx\n\t" \ 1234 "movq 24(%%rax), %%rdx\n\t" \ 1235 "movq 16(%%rax), %%rsi\n\t" \ 1236 "movq 8(%%rax), %%rdi\n\t" \ 1237 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1238 VALGRIND_CALL_NOREDIR_RAX \ 1239 "addq $8, %%rsp\n" \ 1240 "addq $128,%%rsp\n\t" \ 1241 : /*out*/ "=a" (_res) \ 1242 : /*in*/ "a" (&_argvec[0]) \ 1243 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1244 ); \ 1245 lval = (__typeof__(lval)) _res; \ 1246 } while (0) 1247 1248#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1249 arg7,arg8) \ 1250 do { \ 1251 volatile OrigFn _orig = (orig); \ 1252 volatile unsigned long _argvec[9]; \ 1253 volatile unsigned long _res; \ 1254 _argvec[0] = (unsigned long)_orig.nraddr; \ 1255 _argvec[1] = (unsigned long)(arg1); \ 1256 _argvec[2] = (unsigned long)(arg2); \ 1257 _argvec[3] = (unsigned long)(arg3); \ 1258 _argvec[4] = (unsigned long)(arg4); \ 1259 _argvec[5] = (unsigned long)(arg5); \ 1260 _argvec[6] = (unsigned long)(arg6); \ 1261 _argvec[7] = (unsigned long)(arg7); \ 1262 _argvec[8] = (unsigned long)(arg8); \ 1263 __asm__ volatile( \ 1264 "subq $128,%%rsp\n\t" \ 1265 "pushq 64(%%rax)\n\t" \ 1266 "pushq 56(%%rax)\n\t" \ 1267 "movq 48(%%rax), %%r9\n\t" \ 1268 "movq 40(%%rax), %%r8\n\t" \ 1269 "movq 32(%%rax), %%rcx\n\t" \ 1270 "movq 24(%%rax), %%rdx\n\t" \ 1271 "movq 16(%%rax), %%rsi\n\t" \ 1272 "movq 8(%%rax), %%rdi\n\t" \ 1273 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1274 VALGRIND_CALL_NOREDIR_RAX \ 1275 "addq $16, %%rsp\n" \ 1276 "addq $128,%%rsp\n\t" \ 1277 : /*out*/ "=a" (_res) \ 1278 : /*in*/ "a" (&_argvec[0]) \ 1279 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1280 ); \ 1281 lval = (__typeof__(lval)) _res; \ 1282 } while (0) 1283 1284#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1285 arg7,arg8,arg9) \ 1286 do { \ 1287 volatile OrigFn _orig = (orig); \ 1288 volatile unsigned long _argvec[10]; \ 1289 volatile unsigned long _res; \ 1290 _argvec[0] = (unsigned long)_orig.nraddr; \ 1291 _argvec[1] = (unsigned long)(arg1); \ 1292 _argvec[2] = (unsigned long)(arg2); \ 1293 _argvec[3] = (unsigned long)(arg3); \ 1294 _argvec[4] = (unsigned long)(arg4); \ 1295 _argvec[5] = (unsigned long)(arg5); \ 1296 _argvec[6] = (unsigned long)(arg6); \ 1297 _argvec[7] = (unsigned long)(arg7); \ 1298 _argvec[8] = (unsigned long)(arg8); \ 1299 _argvec[9] = (unsigned long)(arg9); \ 1300 __asm__ volatile( \ 1301 "subq $128,%%rsp\n\t" \ 1302 "pushq 72(%%rax)\n\t" \ 1303 "pushq 64(%%rax)\n\t" \ 1304 "pushq 56(%%rax)\n\t" \ 1305 "movq 48(%%rax), %%r9\n\t" \ 1306 "movq 40(%%rax), %%r8\n\t" \ 1307 "movq 32(%%rax), %%rcx\n\t" \ 1308 "movq 24(%%rax), %%rdx\n\t" \ 1309 "movq 16(%%rax), %%rsi\n\t" \ 1310 "movq 8(%%rax), %%rdi\n\t" \ 1311 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1312 VALGRIND_CALL_NOREDIR_RAX \ 1313 "addq $24, %%rsp\n" \ 1314 "addq $128,%%rsp\n\t" \ 1315 : /*out*/ "=a" (_res) \ 1316 : /*in*/ "a" (&_argvec[0]) \ 1317 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1318 ); \ 1319 lval = (__typeof__(lval)) _res; \ 1320 } while (0) 1321 1322#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1323 arg7,arg8,arg9,arg10) \ 1324 do { \ 1325 volatile OrigFn _orig = (orig); \ 1326 volatile unsigned long _argvec[11]; \ 1327 volatile unsigned long _res; \ 1328 _argvec[0] = (unsigned long)_orig.nraddr; \ 1329 _argvec[1] = (unsigned long)(arg1); \ 1330 _argvec[2] = (unsigned long)(arg2); \ 1331 _argvec[3] = (unsigned long)(arg3); \ 1332 _argvec[4] = (unsigned long)(arg4); \ 1333 _argvec[5] = (unsigned long)(arg5); \ 1334 _argvec[6] = (unsigned long)(arg6); \ 1335 _argvec[7] = (unsigned long)(arg7); \ 1336 _argvec[8] = (unsigned long)(arg8); \ 1337 _argvec[9] = (unsigned long)(arg9); \ 1338 _argvec[10] = (unsigned long)(arg10); \ 1339 __asm__ volatile( \ 1340 "subq $128,%%rsp\n\t" \ 1341 "pushq 80(%%rax)\n\t" \ 1342 "pushq 72(%%rax)\n\t" \ 1343 "pushq 64(%%rax)\n\t" \ 1344 "pushq 56(%%rax)\n\t" \ 1345 "movq 48(%%rax), %%r9\n\t" \ 1346 "movq 40(%%rax), %%r8\n\t" \ 1347 "movq 32(%%rax), %%rcx\n\t" \ 1348 "movq 24(%%rax), %%rdx\n\t" \ 1349 "movq 16(%%rax), %%rsi\n\t" \ 1350 "movq 8(%%rax), %%rdi\n\t" \ 1351 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1352 VALGRIND_CALL_NOREDIR_RAX \ 1353 "addq $32, %%rsp\n" \ 1354 "addq $128,%%rsp\n\t" \ 1355 : /*out*/ "=a" (_res) \ 1356 : /*in*/ "a" (&_argvec[0]) \ 1357 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1358 ); \ 1359 lval = (__typeof__(lval)) _res; \ 1360 } while (0) 1361 1362#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1363 arg7,arg8,arg9,arg10,arg11) \ 1364 do { \ 1365 volatile OrigFn _orig = (orig); \ 1366 volatile unsigned long _argvec[12]; \ 1367 volatile unsigned long _res; \ 1368 _argvec[0] = (unsigned long)_orig.nraddr; \ 1369 _argvec[1] = (unsigned long)(arg1); \ 1370 _argvec[2] = (unsigned long)(arg2); \ 1371 _argvec[3] = (unsigned long)(arg3); \ 1372 _argvec[4] = (unsigned long)(arg4); \ 1373 _argvec[5] = (unsigned long)(arg5); \ 1374 _argvec[6] = (unsigned long)(arg6); \ 1375 _argvec[7] = (unsigned long)(arg7); \ 1376 _argvec[8] = (unsigned long)(arg8); \ 1377 _argvec[9] = (unsigned long)(arg9); \ 1378 _argvec[10] = (unsigned long)(arg10); \ 1379 _argvec[11] = (unsigned long)(arg11); \ 1380 __asm__ volatile( \ 1381 "subq $128,%%rsp\n\t" \ 1382 "pushq 88(%%rax)\n\t" \ 1383 "pushq 80(%%rax)\n\t" \ 1384 "pushq 72(%%rax)\n\t" \ 1385 "pushq 64(%%rax)\n\t" \ 1386 "pushq 56(%%rax)\n\t" \ 1387 "movq 48(%%rax), %%r9\n\t" \ 1388 "movq 40(%%rax), %%r8\n\t" \ 1389 "movq 32(%%rax), %%rcx\n\t" \ 1390 "movq 24(%%rax), %%rdx\n\t" \ 1391 "movq 16(%%rax), %%rsi\n\t" \ 1392 "movq 8(%%rax), %%rdi\n\t" \ 1393 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1394 VALGRIND_CALL_NOREDIR_RAX \ 1395 "addq $40, %%rsp\n" \ 1396 "addq $128,%%rsp\n\t" \ 1397 : /*out*/ "=a" (_res) \ 1398 : /*in*/ "a" (&_argvec[0]) \ 1399 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1400 ); \ 1401 lval = (__typeof__(lval)) _res; \ 1402 } while (0) 1403 1404#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1405 arg7,arg8,arg9,arg10,arg11,arg12) \ 1406 do { \ 1407 volatile OrigFn _orig = (orig); \ 1408 volatile unsigned long _argvec[13]; \ 1409 volatile unsigned long _res; \ 1410 _argvec[0] = (unsigned long)_orig.nraddr; \ 1411 _argvec[1] = (unsigned long)(arg1); \ 1412 _argvec[2] = (unsigned long)(arg2); \ 1413 _argvec[3] = (unsigned long)(arg3); \ 1414 _argvec[4] = (unsigned long)(arg4); \ 1415 _argvec[5] = (unsigned long)(arg5); \ 1416 _argvec[6] = (unsigned long)(arg6); \ 1417 _argvec[7] = (unsigned long)(arg7); \ 1418 _argvec[8] = (unsigned long)(arg8); \ 1419 _argvec[9] = (unsigned long)(arg9); \ 1420 _argvec[10] = (unsigned long)(arg10); \ 1421 _argvec[11] = (unsigned long)(arg11); \ 1422 _argvec[12] = (unsigned long)(arg12); \ 1423 __asm__ volatile( \ 1424 "subq $128,%%rsp\n\t" \ 1425 "pushq 96(%%rax)\n\t" \ 1426 "pushq 88(%%rax)\n\t" \ 1427 "pushq 80(%%rax)\n\t" \ 1428 "pushq 72(%%rax)\n\t" \ 1429 "pushq 64(%%rax)\n\t" \ 1430 "pushq 56(%%rax)\n\t" \ 1431 "movq 48(%%rax), %%r9\n\t" \ 1432 "movq 40(%%rax), %%r8\n\t" \ 1433 "movq 32(%%rax), %%rcx\n\t" \ 1434 "movq 24(%%rax), %%rdx\n\t" \ 1435 "movq 16(%%rax), %%rsi\n\t" \ 1436 "movq 8(%%rax), %%rdi\n\t" \ 1437 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1438 VALGRIND_CALL_NOREDIR_RAX \ 1439 "addq $48, %%rsp\n" \ 1440 "addq $128,%%rsp\n\t" \ 1441 : /*out*/ "=a" (_res) \ 1442 : /*in*/ "a" (&_argvec[0]) \ 1443 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1444 ); \ 1445 lval = (__typeof__(lval)) _res; \ 1446 } while (0) 1447 1448#endif /* PLAT_amd64_linux */ 1449 1450/* ------------------------ ppc32-linux ------------------------ */ 1451 1452#if defined(PLAT_ppc32_linux) 1453 1454/* This is useful for finding out about the on-stack stuff: 1455 1456 extern int f9 ( int,int,int,int,int,int,int,int,int ); 1457 extern int f10 ( int,int,int,int,int,int,int,int,int,int ); 1458 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int ); 1459 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int ); 1460 1461 int g9 ( void ) { 1462 return f9(11,22,33,44,55,66,77,88,99); 1463 } 1464 int g10 ( void ) { 1465 return f10(11,22,33,44,55,66,77,88,99,110); 1466 } 1467 int g11 ( void ) { 1468 return f11(11,22,33,44,55,66,77,88,99,110,121); 1469 } 1470 int g12 ( void ) { 1471 return f12(11,22,33,44,55,66,77,88,99,110,121,132); 1472 } 1473*/ 1474 1475/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ 1476 1477/* These regs are trashed by the hidden call. */ 1478#define __CALLER_SAVED_REGS \ 1479 "lr", "ctr", "xer", \ 1480 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ 1481 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ 1482 "r11", "r12", "r13" 1483 1484/* These CALL_FN_ macros assume that on ppc32-linux, 1485 sizeof(unsigned long) == 4. */ 1486 1487#define CALL_FN_W_v(lval, orig) \ 1488 do { \ 1489 volatile OrigFn _orig = (orig); \ 1490 volatile unsigned long _argvec[1]; \ 1491 volatile unsigned long _res; \ 1492 _argvec[0] = (unsigned long)_orig.nraddr; \ 1493 __asm__ volatile( \ 1494 "mr 11,%1\n\t" \ 1495 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1496 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1497 "mr %0,3" \ 1498 : /*out*/ "=r" (_res) \ 1499 : /*in*/ "r" (&_argvec[0]) \ 1500 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1501 ); \ 1502 lval = (__typeof__(lval)) _res; \ 1503 } while (0) 1504 1505#define CALL_FN_W_W(lval, orig, arg1) \ 1506 do { \ 1507 volatile OrigFn _orig = (orig); \ 1508 volatile unsigned long _argvec[2]; \ 1509 volatile unsigned long _res; \ 1510 _argvec[0] = (unsigned long)_orig.nraddr; \ 1511 _argvec[1] = (unsigned long)arg1; \ 1512 __asm__ volatile( \ 1513 "mr 11,%1\n\t" \ 1514 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1515 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1516 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1517 "mr %0,3" \ 1518 : /*out*/ "=r" (_res) \ 1519 : /*in*/ "r" (&_argvec[0]) \ 1520 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1521 ); \ 1522 lval = (__typeof__(lval)) _res; \ 1523 } while (0) 1524 1525#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 1526 do { \ 1527 volatile OrigFn _orig = (orig); \ 1528 volatile unsigned long _argvec[3]; \ 1529 volatile unsigned long _res; \ 1530 _argvec[0] = (unsigned long)_orig.nraddr; \ 1531 _argvec[1] = (unsigned long)arg1; \ 1532 _argvec[2] = (unsigned long)arg2; \ 1533 __asm__ volatile( \ 1534 "mr 11,%1\n\t" \ 1535 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1536 "lwz 4,8(11)\n\t" \ 1537 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1538 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1539 "mr %0,3" \ 1540 : /*out*/ "=r" (_res) \ 1541 : /*in*/ "r" (&_argvec[0]) \ 1542 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1543 ); \ 1544 lval = (__typeof__(lval)) _res; \ 1545 } while (0) 1546 1547#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 1548 do { \ 1549 volatile OrigFn _orig = (orig); \ 1550 volatile unsigned long _argvec[4]; \ 1551 volatile unsigned long _res; \ 1552 _argvec[0] = (unsigned long)_orig.nraddr; \ 1553 _argvec[1] = (unsigned long)arg1; \ 1554 _argvec[2] = (unsigned long)arg2; \ 1555 _argvec[3] = (unsigned long)arg3; \ 1556 __asm__ volatile( \ 1557 "mr 11,%1\n\t" \ 1558 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1559 "lwz 4,8(11)\n\t" \ 1560 "lwz 5,12(11)\n\t" \ 1561 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1562 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1563 "mr %0,3" \ 1564 : /*out*/ "=r" (_res) \ 1565 : /*in*/ "r" (&_argvec[0]) \ 1566 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1567 ); \ 1568 lval = (__typeof__(lval)) _res; \ 1569 } while (0) 1570 1571#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 1572 do { \ 1573 volatile OrigFn _orig = (orig); \ 1574 volatile unsigned long _argvec[5]; \ 1575 volatile unsigned long _res; \ 1576 _argvec[0] = (unsigned long)_orig.nraddr; \ 1577 _argvec[1] = (unsigned long)arg1; \ 1578 _argvec[2] = (unsigned long)arg2; \ 1579 _argvec[3] = (unsigned long)arg3; \ 1580 _argvec[4] = (unsigned long)arg4; \ 1581 __asm__ volatile( \ 1582 "mr 11,%1\n\t" \ 1583 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1584 "lwz 4,8(11)\n\t" \ 1585 "lwz 5,12(11)\n\t" \ 1586 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 1587 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1588 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1589 "mr %0,3" \ 1590 : /*out*/ "=r" (_res) \ 1591 : /*in*/ "r" (&_argvec[0]) \ 1592 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1593 ); \ 1594 lval = (__typeof__(lval)) _res; \ 1595 } while (0) 1596 1597#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 1598 do { \ 1599 volatile OrigFn _orig = (orig); \ 1600 volatile unsigned long _argvec[6]; \ 1601 volatile unsigned long _res; \ 1602 _argvec[0] = (unsigned long)_orig.nraddr; \ 1603 _argvec[1] = (unsigned long)arg1; \ 1604 _argvec[2] = (unsigned long)arg2; \ 1605 _argvec[3] = (unsigned long)arg3; \ 1606 _argvec[4] = (unsigned long)arg4; \ 1607 _argvec[5] = (unsigned long)arg5; \ 1608 __asm__ volatile( \ 1609 "mr 11,%1\n\t" \ 1610 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1611 "lwz 4,8(11)\n\t" \ 1612 "lwz 5,12(11)\n\t" \ 1613 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 1614 "lwz 7,20(11)\n\t" \ 1615 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1616 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1617 "mr %0,3" \ 1618 : /*out*/ "=r" (_res) \ 1619 : /*in*/ "r" (&_argvec[0]) \ 1620 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1621 ); \ 1622 lval = (__typeof__(lval)) _res; \ 1623 } while (0) 1624 1625#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 1626 do { \ 1627 volatile OrigFn _orig = (orig); \ 1628 volatile unsigned long _argvec[7]; \ 1629 volatile unsigned long _res; \ 1630 _argvec[0] = (unsigned long)_orig.nraddr; \ 1631 _argvec[1] = (unsigned long)arg1; \ 1632 _argvec[2] = (unsigned long)arg2; \ 1633 _argvec[3] = (unsigned long)arg3; \ 1634 _argvec[4] = (unsigned long)arg4; \ 1635 _argvec[5] = (unsigned long)arg5; \ 1636 _argvec[6] = (unsigned long)arg6; \ 1637 __asm__ volatile( \ 1638 "mr 11,%1\n\t" \ 1639 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1640 "lwz 4,8(11)\n\t" \ 1641 "lwz 5,12(11)\n\t" \ 1642 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 1643 "lwz 7,20(11)\n\t" \ 1644 "lwz 8,24(11)\n\t" \ 1645 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1646 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1647 "mr %0,3" \ 1648 : /*out*/ "=r" (_res) \ 1649 : /*in*/ "r" (&_argvec[0]) \ 1650 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1651 ); \ 1652 lval = (__typeof__(lval)) _res; \ 1653 } while (0) 1654 1655#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1656 arg7) \ 1657 do { \ 1658 volatile OrigFn _orig = (orig); \ 1659 volatile unsigned long _argvec[8]; \ 1660 volatile unsigned long _res; \ 1661 _argvec[0] = (unsigned long)_orig.nraddr; \ 1662 _argvec[1] = (unsigned long)arg1; \ 1663 _argvec[2] = (unsigned long)arg2; \ 1664 _argvec[3] = (unsigned long)arg3; \ 1665 _argvec[4] = (unsigned long)arg4; \ 1666 _argvec[5] = (unsigned long)arg5; \ 1667 _argvec[6] = (unsigned long)arg6; \ 1668 _argvec[7] = (unsigned long)arg7; \ 1669 __asm__ volatile( \ 1670 "mr 11,%1\n\t" \ 1671 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1672 "lwz 4,8(11)\n\t" \ 1673 "lwz 5,12(11)\n\t" \ 1674 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 1675 "lwz 7,20(11)\n\t" \ 1676 "lwz 8,24(11)\n\t" \ 1677 "lwz 9,28(11)\n\t" \ 1678 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1679 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1680 "mr %0,3" \ 1681 : /*out*/ "=r" (_res) \ 1682 : /*in*/ "r" (&_argvec[0]) \ 1683 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1684 ); \ 1685 lval = (__typeof__(lval)) _res; \ 1686 } while (0) 1687 1688#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1689 arg7,arg8) \ 1690 do { \ 1691 volatile OrigFn _orig = (orig); \ 1692 volatile unsigned long _argvec[9]; \ 1693 volatile unsigned long _res; \ 1694 _argvec[0] = (unsigned long)_orig.nraddr; \ 1695 _argvec[1] = (unsigned long)arg1; \ 1696 _argvec[2] = (unsigned long)arg2; \ 1697 _argvec[3] = (unsigned long)arg3; \ 1698 _argvec[4] = (unsigned long)arg4; \ 1699 _argvec[5] = (unsigned long)arg5; \ 1700 _argvec[6] = (unsigned long)arg6; \ 1701 _argvec[7] = (unsigned long)arg7; \ 1702 _argvec[8] = (unsigned long)arg8; \ 1703 __asm__ volatile( \ 1704 "mr 11,%1\n\t" \ 1705 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1706 "lwz 4,8(11)\n\t" \ 1707 "lwz 5,12(11)\n\t" \ 1708 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 1709 "lwz 7,20(11)\n\t" \ 1710 "lwz 8,24(11)\n\t" \ 1711 "lwz 9,28(11)\n\t" \ 1712 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 1713 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1714 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1715 "mr %0,3" \ 1716 : /*out*/ "=r" (_res) \ 1717 : /*in*/ "r" (&_argvec[0]) \ 1718 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1719 ); \ 1720 lval = (__typeof__(lval)) _res; \ 1721 } while (0) 1722 1723#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1724 arg7,arg8,arg9) \ 1725 do { \ 1726 volatile OrigFn _orig = (orig); \ 1727 volatile unsigned long _argvec[10]; \ 1728 volatile unsigned long _res; \ 1729 _argvec[0] = (unsigned long)_orig.nraddr; \ 1730 _argvec[1] = (unsigned long)arg1; \ 1731 _argvec[2] = (unsigned long)arg2; \ 1732 _argvec[3] = (unsigned long)arg3; \ 1733 _argvec[4] = (unsigned long)arg4; \ 1734 _argvec[5] = (unsigned long)arg5; \ 1735 _argvec[6] = (unsigned long)arg6; \ 1736 _argvec[7] = (unsigned long)arg7; \ 1737 _argvec[8] = (unsigned long)arg8; \ 1738 _argvec[9] = (unsigned long)arg9; \ 1739 __asm__ volatile( \ 1740 "mr 11,%1\n\t" \ 1741 "addi 1,1,-16\n\t" \ 1742 /* arg9 */ \ 1743 "lwz 3,36(11)\n\t" \ 1744 "stw 3,8(1)\n\t" \ 1745 /* args1-8 */ \ 1746 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1747 "lwz 4,8(11)\n\t" \ 1748 "lwz 5,12(11)\n\t" \ 1749 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 1750 "lwz 7,20(11)\n\t" \ 1751 "lwz 8,24(11)\n\t" \ 1752 "lwz 9,28(11)\n\t" \ 1753 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 1754 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1755 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1756 "addi 1,1,16\n\t" \ 1757 "mr %0,3" \ 1758 : /*out*/ "=r" (_res) \ 1759 : /*in*/ "r" (&_argvec[0]) \ 1760 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1761 ); \ 1762 lval = (__typeof__(lval)) _res; \ 1763 } while (0) 1764 1765#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1766 arg7,arg8,arg9,arg10) \ 1767 do { \ 1768 volatile OrigFn _orig = (orig); \ 1769 volatile unsigned long _argvec[11]; \ 1770 volatile unsigned long _res; \ 1771 _argvec[0] = (unsigned long)_orig.nraddr; \ 1772 _argvec[1] = (unsigned long)arg1; \ 1773 _argvec[2] = (unsigned long)arg2; \ 1774 _argvec[3] = (unsigned long)arg3; \ 1775 _argvec[4] = (unsigned long)arg4; \ 1776 _argvec[5] = (unsigned long)arg5; \ 1777 _argvec[6] = (unsigned long)arg6; \ 1778 _argvec[7] = (unsigned long)arg7; \ 1779 _argvec[8] = (unsigned long)arg8; \ 1780 _argvec[9] = (unsigned long)arg9; \ 1781 _argvec[10] = (unsigned long)arg10; \ 1782 __asm__ volatile( \ 1783 "mr 11,%1\n\t" \ 1784 "addi 1,1,-16\n\t" \ 1785 /* arg10 */ \ 1786 "lwz 3,40(11)\n\t" \ 1787 "stw 3,12(1)\n\t" \ 1788 /* arg9 */ \ 1789 "lwz 3,36(11)\n\t" \ 1790 "stw 3,8(1)\n\t" \ 1791 /* args1-8 */ \ 1792 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1793 "lwz 4,8(11)\n\t" \ 1794 "lwz 5,12(11)\n\t" \ 1795 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 1796 "lwz 7,20(11)\n\t" \ 1797 "lwz 8,24(11)\n\t" \ 1798 "lwz 9,28(11)\n\t" \ 1799 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 1800 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1801 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1802 "addi 1,1,16\n\t" \ 1803 "mr %0,3" \ 1804 : /*out*/ "=r" (_res) \ 1805 : /*in*/ "r" (&_argvec[0]) \ 1806 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1807 ); \ 1808 lval = (__typeof__(lval)) _res; \ 1809 } while (0) 1810 1811#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1812 arg7,arg8,arg9,arg10,arg11) \ 1813 do { \ 1814 volatile OrigFn _orig = (orig); \ 1815 volatile unsigned long _argvec[12]; \ 1816 volatile unsigned long _res; \ 1817 _argvec[0] = (unsigned long)_orig.nraddr; \ 1818 _argvec[1] = (unsigned long)arg1; \ 1819 _argvec[2] = (unsigned long)arg2; \ 1820 _argvec[3] = (unsigned long)arg3; \ 1821 _argvec[4] = (unsigned long)arg4; \ 1822 _argvec[5] = (unsigned long)arg5; \ 1823 _argvec[6] = (unsigned long)arg6; \ 1824 _argvec[7] = (unsigned long)arg7; \ 1825 _argvec[8] = (unsigned long)arg8; \ 1826 _argvec[9] = (unsigned long)arg9; \ 1827 _argvec[10] = (unsigned long)arg10; \ 1828 _argvec[11] = (unsigned long)arg11; \ 1829 __asm__ volatile( \ 1830 "mr 11,%1\n\t" \ 1831 "addi 1,1,-32\n\t" \ 1832 /* arg11 */ \ 1833 "lwz 3,44(11)\n\t" \ 1834 "stw 3,16(1)\n\t" \ 1835 /* arg10 */ \ 1836 "lwz 3,40(11)\n\t" \ 1837 "stw 3,12(1)\n\t" \ 1838 /* arg9 */ \ 1839 "lwz 3,36(11)\n\t" \ 1840 "stw 3,8(1)\n\t" \ 1841 /* args1-8 */ \ 1842 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1843 "lwz 4,8(11)\n\t" \ 1844 "lwz 5,12(11)\n\t" \ 1845 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 1846 "lwz 7,20(11)\n\t" \ 1847 "lwz 8,24(11)\n\t" \ 1848 "lwz 9,28(11)\n\t" \ 1849 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 1850 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1851 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1852 "addi 1,1,32\n\t" \ 1853 "mr %0,3" \ 1854 : /*out*/ "=r" (_res) \ 1855 : /*in*/ "r" (&_argvec[0]) \ 1856 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1857 ); \ 1858 lval = (__typeof__(lval)) _res; \ 1859 } while (0) 1860 1861#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1862 arg7,arg8,arg9,arg10,arg11,arg12) \ 1863 do { \ 1864 volatile OrigFn _orig = (orig); \ 1865 volatile unsigned long _argvec[13]; \ 1866 volatile unsigned long _res; \ 1867 _argvec[0] = (unsigned long)_orig.nraddr; \ 1868 _argvec[1] = (unsigned long)arg1; \ 1869 _argvec[2] = (unsigned long)arg2; \ 1870 _argvec[3] = (unsigned long)arg3; \ 1871 _argvec[4] = (unsigned long)arg4; \ 1872 _argvec[5] = (unsigned long)arg5; \ 1873 _argvec[6] = (unsigned long)arg6; \ 1874 _argvec[7] = (unsigned long)arg7; \ 1875 _argvec[8] = (unsigned long)arg8; \ 1876 _argvec[9] = (unsigned long)arg9; \ 1877 _argvec[10] = (unsigned long)arg10; \ 1878 _argvec[11] = (unsigned long)arg11; \ 1879 _argvec[12] = (unsigned long)arg12; \ 1880 __asm__ volatile( \ 1881 "mr 11,%1\n\t" \ 1882 "addi 1,1,-32\n\t" \ 1883 /* arg12 */ \ 1884 "lwz 3,48(11)\n\t" \ 1885 "stw 3,20(1)\n\t" \ 1886 /* arg11 */ \ 1887 "lwz 3,44(11)\n\t" \ 1888 "stw 3,16(1)\n\t" \ 1889 /* arg10 */ \ 1890 "lwz 3,40(11)\n\t" \ 1891 "stw 3,12(1)\n\t" \ 1892 /* arg9 */ \ 1893 "lwz 3,36(11)\n\t" \ 1894 "stw 3,8(1)\n\t" \ 1895 /* args1-8 */ \ 1896 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1897 "lwz 4,8(11)\n\t" \ 1898 "lwz 5,12(11)\n\t" \ 1899 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 1900 "lwz 7,20(11)\n\t" \ 1901 "lwz 8,24(11)\n\t" \ 1902 "lwz 9,28(11)\n\t" \ 1903 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 1904 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1905 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1906 "addi 1,1,32\n\t" \ 1907 "mr %0,3" \ 1908 : /*out*/ "=r" (_res) \ 1909 : /*in*/ "r" (&_argvec[0]) \ 1910 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1911 ); \ 1912 lval = (__typeof__(lval)) _res; \ 1913 } while (0) 1914 1915#endif /* PLAT_ppc32_linux */ 1916 1917/* ------------------------ ppc64-linux ------------------------ */ 1918 1919#if defined(PLAT_ppc64_linux) 1920 1921/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ 1922 1923/* These regs are trashed by the hidden call. */ 1924#define __CALLER_SAVED_REGS \ 1925 "lr", "ctr", "xer", \ 1926 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ 1927 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ 1928 "r11", "r12", "r13" 1929 1930/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned 1931 long) == 8. */ 1932 1933#define CALL_FN_W_v(lval, orig) \ 1934 do { \ 1935 volatile OrigFn _orig = (orig); \ 1936 volatile unsigned long _argvec[3+0]; \ 1937 volatile unsigned long _res; \ 1938 /* _argvec[0] holds current r2 across the call */ \ 1939 _argvec[1] = (unsigned long)_orig.r2; \ 1940 _argvec[2] = (unsigned long)_orig.nraddr; \ 1941 __asm__ volatile( \ 1942 "mr 11,%1\n\t" \ 1943 "std 2,-16(11)\n\t" /* save tocptr */ \ 1944 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 1945 "ld 11, 0(11)\n\t" /* target->r11 */ \ 1946 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1947 "mr 11,%1\n\t" \ 1948 "mr %0,3\n\t" \ 1949 "ld 2,-16(11)" /* restore tocptr */ \ 1950 : /*out*/ "=r" (_res) \ 1951 : /*in*/ "r" (&_argvec[2]) \ 1952 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1953 ); \ 1954 lval = (__typeof__(lval)) _res; \ 1955 } while (0) 1956 1957#define CALL_FN_W_W(lval, orig, arg1) \ 1958 do { \ 1959 volatile OrigFn _orig = (orig); \ 1960 volatile unsigned long _argvec[3+1]; \ 1961 volatile unsigned long _res; \ 1962 /* _argvec[0] holds current r2 across the call */ \ 1963 _argvec[1] = (unsigned long)_orig.r2; \ 1964 _argvec[2] = (unsigned long)_orig.nraddr; \ 1965 _argvec[2+1] = (unsigned long)arg1; \ 1966 __asm__ volatile( \ 1967 "mr 11,%1\n\t" \ 1968 "std 2,-16(11)\n\t" /* save tocptr */ \ 1969 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 1970 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 1971 "ld 11, 0(11)\n\t" /* target->r11 */ \ 1972 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1973 "mr 11,%1\n\t" \ 1974 "mr %0,3\n\t" \ 1975 "ld 2,-16(11)" /* restore tocptr */ \ 1976 : /*out*/ "=r" (_res) \ 1977 : /*in*/ "r" (&_argvec[2]) \ 1978 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1979 ); \ 1980 lval = (__typeof__(lval)) _res; \ 1981 } while (0) 1982 1983#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 1984 do { \ 1985 volatile OrigFn _orig = (orig); \ 1986 volatile unsigned long _argvec[3+2]; \ 1987 volatile unsigned long _res; \ 1988 /* _argvec[0] holds current r2 across the call */ \ 1989 _argvec[1] = (unsigned long)_orig.r2; \ 1990 _argvec[2] = (unsigned long)_orig.nraddr; \ 1991 _argvec[2+1] = (unsigned long)arg1; \ 1992 _argvec[2+2] = (unsigned long)arg2; \ 1993 __asm__ volatile( \ 1994 "mr 11,%1\n\t" \ 1995 "std 2,-16(11)\n\t" /* save tocptr */ \ 1996 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 1997 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 1998 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 1999 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2000 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2001 "mr 11,%1\n\t" \ 2002 "mr %0,3\n\t" \ 2003 "ld 2,-16(11)" /* restore tocptr */ \ 2004 : /*out*/ "=r" (_res) \ 2005 : /*in*/ "r" (&_argvec[2]) \ 2006 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2007 ); \ 2008 lval = (__typeof__(lval)) _res; \ 2009 } while (0) 2010 2011#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 2012 do { \ 2013 volatile OrigFn _orig = (orig); \ 2014 volatile unsigned long _argvec[3+3]; \ 2015 volatile unsigned long _res; \ 2016 /* _argvec[0] holds current r2 across the call */ \ 2017 _argvec[1] = (unsigned long)_orig.r2; \ 2018 _argvec[2] = (unsigned long)_orig.nraddr; \ 2019 _argvec[2+1] = (unsigned long)arg1; \ 2020 _argvec[2+2] = (unsigned long)arg2; \ 2021 _argvec[2+3] = (unsigned long)arg3; \ 2022 __asm__ volatile( \ 2023 "mr 11,%1\n\t" \ 2024 "std 2,-16(11)\n\t" /* save tocptr */ \ 2025 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2026 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2027 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2028 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2029 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2030 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2031 "mr 11,%1\n\t" \ 2032 "mr %0,3\n\t" \ 2033 "ld 2,-16(11)" /* restore tocptr */ \ 2034 : /*out*/ "=r" (_res) \ 2035 : /*in*/ "r" (&_argvec[2]) \ 2036 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2037 ); \ 2038 lval = (__typeof__(lval)) _res; \ 2039 } while (0) 2040 2041#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 2042 do { \ 2043 volatile OrigFn _orig = (orig); \ 2044 volatile unsigned long _argvec[3+4]; \ 2045 volatile unsigned long _res; \ 2046 /* _argvec[0] holds current r2 across the call */ \ 2047 _argvec[1] = (unsigned long)_orig.r2; \ 2048 _argvec[2] = (unsigned long)_orig.nraddr; \ 2049 _argvec[2+1] = (unsigned long)arg1; \ 2050 _argvec[2+2] = (unsigned long)arg2; \ 2051 _argvec[2+3] = (unsigned long)arg3; \ 2052 _argvec[2+4] = (unsigned long)arg4; \ 2053 __asm__ volatile( \ 2054 "mr 11,%1\n\t" \ 2055 "std 2,-16(11)\n\t" /* save tocptr */ \ 2056 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2057 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2058 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2059 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2060 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2061 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2062 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2063 "mr 11,%1\n\t" \ 2064 "mr %0,3\n\t" \ 2065 "ld 2,-16(11)" /* restore tocptr */ \ 2066 : /*out*/ "=r" (_res) \ 2067 : /*in*/ "r" (&_argvec[2]) \ 2068 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2069 ); \ 2070 lval = (__typeof__(lval)) _res; \ 2071 } while (0) 2072 2073#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 2074 do { \ 2075 volatile OrigFn _orig = (orig); \ 2076 volatile unsigned long _argvec[3+5]; \ 2077 volatile unsigned long _res; \ 2078 /* _argvec[0] holds current r2 across the call */ \ 2079 _argvec[1] = (unsigned long)_orig.r2; \ 2080 _argvec[2] = (unsigned long)_orig.nraddr; \ 2081 _argvec[2+1] = (unsigned long)arg1; \ 2082 _argvec[2+2] = (unsigned long)arg2; \ 2083 _argvec[2+3] = (unsigned long)arg3; \ 2084 _argvec[2+4] = (unsigned long)arg4; \ 2085 _argvec[2+5] = (unsigned long)arg5; \ 2086 __asm__ volatile( \ 2087 "mr 11,%1\n\t" \ 2088 "std 2,-16(11)\n\t" /* save tocptr */ \ 2089 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2090 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2091 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2092 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2093 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2094 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2095 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2096 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2097 "mr 11,%1\n\t" \ 2098 "mr %0,3\n\t" \ 2099 "ld 2,-16(11)" /* restore tocptr */ \ 2100 : /*out*/ "=r" (_res) \ 2101 : /*in*/ "r" (&_argvec[2]) \ 2102 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2103 ); \ 2104 lval = (__typeof__(lval)) _res; \ 2105 } while (0) 2106 2107#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 2108 do { \ 2109 volatile OrigFn _orig = (orig); \ 2110 volatile unsigned long _argvec[3+6]; \ 2111 volatile unsigned long _res; \ 2112 /* _argvec[0] holds current r2 across the call */ \ 2113 _argvec[1] = (unsigned long)_orig.r2; \ 2114 _argvec[2] = (unsigned long)_orig.nraddr; \ 2115 _argvec[2+1] = (unsigned long)arg1; \ 2116 _argvec[2+2] = (unsigned long)arg2; \ 2117 _argvec[2+3] = (unsigned long)arg3; \ 2118 _argvec[2+4] = (unsigned long)arg4; \ 2119 _argvec[2+5] = (unsigned long)arg5; \ 2120 _argvec[2+6] = (unsigned long)arg6; \ 2121 __asm__ volatile( \ 2122 "mr 11,%1\n\t" \ 2123 "std 2,-16(11)\n\t" /* save tocptr */ \ 2124 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2125 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2126 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2127 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2128 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2129 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2130 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2131 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2132 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2133 "mr 11,%1\n\t" \ 2134 "mr %0,3\n\t" \ 2135 "ld 2,-16(11)" /* restore tocptr */ \ 2136 : /*out*/ "=r" (_res) \ 2137 : /*in*/ "r" (&_argvec[2]) \ 2138 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2139 ); \ 2140 lval = (__typeof__(lval)) _res; \ 2141 } while (0) 2142 2143#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2144 arg7) \ 2145 do { \ 2146 volatile OrigFn _orig = (orig); \ 2147 volatile unsigned long _argvec[3+7]; \ 2148 volatile unsigned long _res; \ 2149 /* _argvec[0] holds current r2 across the call */ \ 2150 _argvec[1] = (unsigned long)_orig.r2; \ 2151 _argvec[2] = (unsigned long)_orig.nraddr; \ 2152 _argvec[2+1] = (unsigned long)arg1; \ 2153 _argvec[2+2] = (unsigned long)arg2; \ 2154 _argvec[2+3] = (unsigned long)arg3; \ 2155 _argvec[2+4] = (unsigned long)arg4; \ 2156 _argvec[2+5] = (unsigned long)arg5; \ 2157 _argvec[2+6] = (unsigned long)arg6; \ 2158 _argvec[2+7] = (unsigned long)arg7; \ 2159 __asm__ volatile( \ 2160 "mr 11,%1\n\t" \ 2161 "std 2,-16(11)\n\t" /* save tocptr */ \ 2162 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2163 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2164 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2165 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2166 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2167 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2168 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2169 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 2170 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2171 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2172 "mr 11,%1\n\t" \ 2173 "mr %0,3\n\t" \ 2174 "ld 2,-16(11)" /* restore tocptr */ \ 2175 : /*out*/ "=r" (_res) \ 2176 : /*in*/ "r" (&_argvec[2]) \ 2177 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2178 ); \ 2179 lval = (__typeof__(lval)) _res; \ 2180 } while (0) 2181 2182#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2183 arg7,arg8) \ 2184 do { \ 2185 volatile OrigFn _orig = (orig); \ 2186 volatile unsigned long _argvec[3+8]; \ 2187 volatile unsigned long _res; \ 2188 /* _argvec[0] holds current r2 across the call */ \ 2189 _argvec[1] = (unsigned long)_orig.r2; \ 2190 _argvec[2] = (unsigned long)_orig.nraddr; \ 2191 _argvec[2+1] = (unsigned long)arg1; \ 2192 _argvec[2+2] = (unsigned long)arg2; \ 2193 _argvec[2+3] = (unsigned long)arg3; \ 2194 _argvec[2+4] = (unsigned long)arg4; \ 2195 _argvec[2+5] = (unsigned long)arg5; \ 2196 _argvec[2+6] = (unsigned long)arg6; \ 2197 _argvec[2+7] = (unsigned long)arg7; \ 2198 _argvec[2+8] = (unsigned long)arg8; \ 2199 __asm__ volatile( \ 2200 "mr 11,%1\n\t" \ 2201 "std 2,-16(11)\n\t" /* save tocptr */ \ 2202 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2203 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2204 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2205 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2206 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2207 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2208 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2209 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 2210 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 2211 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2212 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2213 "mr 11,%1\n\t" \ 2214 "mr %0,3\n\t" \ 2215 "ld 2,-16(11)" /* restore tocptr */ \ 2216 : /*out*/ "=r" (_res) \ 2217 : /*in*/ "r" (&_argvec[2]) \ 2218 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2219 ); \ 2220 lval = (__typeof__(lval)) _res; \ 2221 } while (0) 2222 2223#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2224 arg7,arg8,arg9) \ 2225 do { \ 2226 volatile OrigFn _orig = (orig); \ 2227 volatile unsigned long _argvec[3+9]; \ 2228 volatile unsigned long _res; \ 2229 /* _argvec[0] holds current r2 across the call */ \ 2230 _argvec[1] = (unsigned long)_orig.r2; \ 2231 _argvec[2] = (unsigned long)_orig.nraddr; \ 2232 _argvec[2+1] = (unsigned long)arg1; \ 2233 _argvec[2+2] = (unsigned long)arg2; \ 2234 _argvec[2+3] = (unsigned long)arg3; \ 2235 _argvec[2+4] = (unsigned long)arg4; \ 2236 _argvec[2+5] = (unsigned long)arg5; \ 2237 _argvec[2+6] = (unsigned long)arg6; \ 2238 _argvec[2+7] = (unsigned long)arg7; \ 2239 _argvec[2+8] = (unsigned long)arg8; \ 2240 _argvec[2+9] = (unsigned long)arg9; \ 2241 __asm__ volatile( \ 2242 "mr 11,%1\n\t" \ 2243 "std 2,-16(11)\n\t" /* save tocptr */ \ 2244 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2245 "addi 1,1,-128\n\t" /* expand stack frame */ \ 2246 /* arg9 */ \ 2247 "ld 3,72(11)\n\t" \ 2248 "std 3,112(1)\n\t" \ 2249 /* args1-8 */ \ 2250 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2251 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2252 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2253 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2254 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2255 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2256 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 2257 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 2258 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2259 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2260 "mr 11,%1\n\t" \ 2261 "mr %0,3\n\t" \ 2262 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2263 "addi 1,1,128" /* restore frame */ \ 2264 : /*out*/ "=r" (_res) \ 2265 : /*in*/ "r" (&_argvec[2]) \ 2266 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2267 ); \ 2268 lval = (__typeof__(lval)) _res; \ 2269 } while (0) 2270 2271#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2272 arg7,arg8,arg9,arg10) \ 2273 do { \ 2274 volatile OrigFn _orig = (orig); \ 2275 volatile unsigned long _argvec[3+10]; \ 2276 volatile unsigned long _res; \ 2277 /* _argvec[0] holds current r2 across the call */ \ 2278 _argvec[1] = (unsigned long)_orig.r2; \ 2279 _argvec[2] = (unsigned long)_orig.nraddr; \ 2280 _argvec[2+1] = (unsigned long)arg1; \ 2281 _argvec[2+2] = (unsigned long)arg2; \ 2282 _argvec[2+3] = (unsigned long)arg3; \ 2283 _argvec[2+4] = (unsigned long)arg4; \ 2284 _argvec[2+5] = (unsigned long)arg5; \ 2285 _argvec[2+6] = (unsigned long)arg6; \ 2286 _argvec[2+7] = (unsigned long)arg7; \ 2287 _argvec[2+8] = (unsigned long)arg8; \ 2288 _argvec[2+9] = (unsigned long)arg9; \ 2289 _argvec[2+10] = (unsigned long)arg10; \ 2290 __asm__ volatile( \ 2291 "mr 11,%1\n\t" \ 2292 "std 2,-16(11)\n\t" /* save tocptr */ \ 2293 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2294 "addi 1,1,-128\n\t" /* expand stack frame */ \ 2295 /* arg10 */ \ 2296 "ld 3,80(11)\n\t" \ 2297 "std 3,120(1)\n\t" \ 2298 /* arg9 */ \ 2299 "ld 3,72(11)\n\t" \ 2300 "std 3,112(1)\n\t" \ 2301 /* args1-8 */ \ 2302 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2303 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2304 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2305 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2306 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2307 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2308 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 2309 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 2310 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2311 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2312 "mr 11,%1\n\t" \ 2313 "mr %0,3\n\t" \ 2314 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2315 "addi 1,1,128" /* restore frame */ \ 2316 : /*out*/ "=r" (_res) \ 2317 : /*in*/ "r" (&_argvec[2]) \ 2318 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2319 ); \ 2320 lval = (__typeof__(lval)) _res; \ 2321 } while (0) 2322 2323#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2324 arg7,arg8,arg9,arg10,arg11) \ 2325 do { \ 2326 volatile OrigFn _orig = (orig); \ 2327 volatile unsigned long _argvec[3+11]; \ 2328 volatile unsigned long _res; \ 2329 /* _argvec[0] holds current r2 across the call */ \ 2330 _argvec[1] = (unsigned long)_orig.r2; \ 2331 _argvec[2] = (unsigned long)_orig.nraddr; \ 2332 _argvec[2+1] = (unsigned long)arg1; \ 2333 _argvec[2+2] = (unsigned long)arg2; \ 2334 _argvec[2+3] = (unsigned long)arg3; \ 2335 _argvec[2+4] = (unsigned long)arg4; \ 2336 _argvec[2+5] = (unsigned long)arg5; \ 2337 _argvec[2+6] = (unsigned long)arg6; \ 2338 _argvec[2+7] = (unsigned long)arg7; \ 2339 _argvec[2+8] = (unsigned long)arg8; \ 2340 _argvec[2+9] = (unsigned long)arg9; \ 2341 _argvec[2+10] = (unsigned long)arg10; \ 2342 _argvec[2+11] = (unsigned long)arg11; \ 2343 __asm__ volatile( \ 2344 "mr 11,%1\n\t" \ 2345 "std 2,-16(11)\n\t" /* save tocptr */ \ 2346 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2347 "addi 1,1,-144\n\t" /* expand stack frame */ \ 2348 /* arg11 */ \ 2349 "ld 3,88(11)\n\t" \ 2350 "std 3,128(1)\n\t" \ 2351 /* arg10 */ \ 2352 "ld 3,80(11)\n\t" \ 2353 "std 3,120(1)\n\t" \ 2354 /* arg9 */ \ 2355 "ld 3,72(11)\n\t" \ 2356 "std 3,112(1)\n\t" \ 2357 /* args1-8 */ \ 2358 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2359 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2360 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2361 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2362 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2363 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2364 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 2365 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 2366 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2367 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2368 "mr 11,%1\n\t" \ 2369 "mr %0,3\n\t" \ 2370 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2371 "addi 1,1,144" /* restore frame */ \ 2372 : /*out*/ "=r" (_res) \ 2373 : /*in*/ "r" (&_argvec[2]) \ 2374 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2375 ); \ 2376 lval = (__typeof__(lval)) _res; \ 2377 } while (0) 2378 2379#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2380 arg7,arg8,arg9,arg10,arg11,arg12) \ 2381 do { \ 2382 volatile OrigFn _orig = (orig); \ 2383 volatile unsigned long _argvec[3+12]; \ 2384 volatile unsigned long _res; \ 2385 /* _argvec[0] holds current r2 across the call */ \ 2386 _argvec[1] = (unsigned long)_orig.r2; \ 2387 _argvec[2] = (unsigned long)_orig.nraddr; \ 2388 _argvec[2+1] = (unsigned long)arg1; \ 2389 _argvec[2+2] = (unsigned long)arg2; \ 2390 _argvec[2+3] = (unsigned long)arg3; \ 2391 _argvec[2+4] = (unsigned long)arg4; \ 2392 _argvec[2+5] = (unsigned long)arg5; \ 2393 _argvec[2+6] = (unsigned long)arg6; \ 2394 _argvec[2+7] = (unsigned long)arg7; \ 2395 _argvec[2+8] = (unsigned long)arg8; \ 2396 _argvec[2+9] = (unsigned long)arg9; \ 2397 _argvec[2+10] = (unsigned long)arg10; \ 2398 _argvec[2+11] = (unsigned long)arg11; \ 2399 _argvec[2+12] = (unsigned long)arg12; \ 2400 __asm__ volatile( \ 2401 "mr 11,%1\n\t" \ 2402 "std 2,-16(11)\n\t" /* save tocptr */ \ 2403 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2404 "addi 1,1,-144\n\t" /* expand stack frame */ \ 2405 /* arg12 */ \ 2406 "ld 3,96(11)\n\t" \ 2407 "std 3,136(1)\n\t" \ 2408 /* arg11 */ \ 2409 "ld 3,88(11)\n\t" \ 2410 "std 3,128(1)\n\t" \ 2411 /* arg10 */ \ 2412 "ld 3,80(11)\n\t" \ 2413 "std 3,120(1)\n\t" \ 2414 /* arg9 */ \ 2415 "ld 3,72(11)\n\t" \ 2416 "std 3,112(1)\n\t" \ 2417 /* args1-8 */ \ 2418 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2419 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2420 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2421 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2422 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2423 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2424 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 2425 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 2426 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2427 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2428 "mr 11,%1\n\t" \ 2429 "mr %0,3\n\t" \ 2430 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2431 "addi 1,1,144" /* restore frame */ \ 2432 : /*out*/ "=r" (_res) \ 2433 : /*in*/ "r" (&_argvec[2]) \ 2434 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2435 ); \ 2436 lval = (__typeof__(lval)) _res; \ 2437 } while (0) 2438 2439#endif /* PLAT_ppc64_linux */ 2440 2441/* ------------------------ ppc32-aix5 ------------------------- */ 2442 2443#if defined(PLAT_ppc32_aix5) 2444 2445/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ 2446 2447/* These regs are trashed by the hidden call. */ 2448#define __CALLER_SAVED_REGS \ 2449 "lr", "ctr", "xer", \ 2450 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ 2451 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ 2452 "r11", "r12", "r13" 2453 2454/* Expand the stack frame, copying enough info that unwinding 2455 still works. Trashes r3. */ 2456 2457#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \ 2458 "addi 1,1,-" #_n_fr "\n\t" \ 2459 "lwz 3," #_n_fr "(1)\n\t" \ 2460 "stw 3,0(1)\n\t" 2461 2462#define VG_CONTRACT_FRAME_BY(_n_fr) \ 2463 "addi 1,1," #_n_fr "\n\t" 2464 2465/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned 2466 long) == 4. */ 2467 2468#define CALL_FN_W_v(lval, orig) \ 2469 do { \ 2470 volatile OrigFn _orig = (orig); \ 2471 volatile unsigned long _argvec[3+0]; \ 2472 volatile unsigned long _res; \ 2473 /* _argvec[0] holds current r2 across the call */ \ 2474 _argvec[1] = (unsigned long)_orig.r2; \ 2475 _argvec[2] = (unsigned long)_orig.nraddr; \ 2476 __asm__ volatile( \ 2477 "mr 11,%1\n\t" \ 2478 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 2479 "stw 2,-8(11)\n\t" /* save tocptr */ \ 2480 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 2481 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 2482 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2483 "mr 11,%1\n\t" \ 2484 "mr %0,3\n\t" \ 2485 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 2486 VG_CONTRACT_FRAME_BY(512) \ 2487 : /*out*/ "=r" (_res) \ 2488 : /*in*/ "r" (&_argvec[2]) \ 2489 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2490 ); \ 2491 lval = (__typeof__(lval)) _res; \ 2492 } while (0) 2493 2494#define CALL_FN_W_W(lval, orig, arg1) \ 2495 do { \ 2496 volatile OrigFn _orig = (orig); \ 2497 volatile unsigned long _argvec[3+1]; \ 2498 volatile unsigned long _res; \ 2499 /* _argvec[0] holds current r2 across the call */ \ 2500 _argvec[1] = (unsigned long)_orig.r2; \ 2501 _argvec[2] = (unsigned long)_orig.nraddr; \ 2502 _argvec[2+1] = (unsigned long)arg1; \ 2503 __asm__ volatile( \ 2504 "mr 11,%1\n\t" \ 2505 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 2506 "stw 2,-8(11)\n\t" /* save tocptr */ \ 2507 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 2508 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 2509 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 2510 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2511 "mr 11,%1\n\t" \ 2512 "mr %0,3\n\t" \ 2513 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 2514 VG_CONTRACT_FRAME_BY(512) \ 2515 : /*out*/ "=r" (_res) \ 2516 : /*in*/ "r" (&_argvec[2]) \ 2517 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2518 ); \ 2519 lval = (__typeof__(lval)) _res; \ 2520 } while (0) 2521 2522#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 2523 do { \ 2524 volatile OrigFn _orig = (orig); \ 2525 volatile unsigned long _argvec[3+2]; \ 2526 volatile unsigned long _res; \ 2527 /* _argvec[0] holds current r2 across the call */ \ 2528 _argvec[1] = (unsigned long)_orig.r2; \ 2529 _argvec[2] = (unsigned long)_orig.nraddr; \ 2530 _argvec[2+1] = (unsigned long)arg1; \ 2531 _argvec[2+2] = (unsigned long)arg2; \ 2532 __asm__ volatile( \ 2533 "mr 11,%1\n\t" \ 2534 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 2535 "stw 2,-8(11)\n\t" /* save tocptr */ \ 2536 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 2537 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 2538 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 2539 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 2540 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2541 "mr 11,%1\n\t" \ 2542 "mr %0,3\n\t" \ 2543 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 2544 VG_CONTRACT_FRAME_BY(512) \ 2545 : /*out*/ "=r" (_res) \ 2546 : /*in*/ "r" (&_argvec[2]) \ 2547 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2548 ); \ 2549 lval = (__typeof__(lval)) _res; \ 2550 } while (0) 2551 2552#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 2553 do { \ 2554 volatile OrigFn _orig = (orig); \ 2555 volatile unsigned long _argvec[3+3]; \ 2556 volatile unsigned long _res; \ 2557 /* _argvec[0] holds current r2 across the call */ \ 2558 _argvec[1] = (unsigned long)_orig.r2; \ 2559 _argvec[2] = (unsigned long)_orig.nraddr; \ 2560 _argvec[2+1] = (unsigned long)arg1; \ 2561 _argvec[2+2] = (unsigned long)arg2; \ 2562 _argvec[2+3] = (unsigned long)arg3; \ 2563 __asm__ volatile( \ 2564 "mr 11,%1\n\t" \ 2565 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 2566 "stw 2,-8(11)\n\t" /* save tocptr */ \ 2567 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 2568 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 2569 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 2570 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 2571 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 2572 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2573 "mr 11,%1\n\t" \ 2574 "mr %0,3\n\t" \ 2575 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 2576 VG_CONTRACT_FRAME_BY(512) \ 2577 : /*out*/ "=r" (_res) \ 2578 : /*in*/ "r" (&_argvec[2]) \ 2579 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2580 ); \ 2581 lval = (__typeof__(lval)) _res; \ 2582 } while (0) 2583 2584#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 2585 do { \ 2586 volatile OrigFn _orig = (orig); \ 2587 volatile unsigned long _argvec[3+4]; \ 2588 volatile unsigned long _res; \ 2589 /* _argvec[0] holds current r2 across the call */ \ 2590 _argvec[1] = (unsigned long)_orig.r2; \ 2591 _argvec[2] = (unsigned long)_orig.nraddr; \ 2592 _argvec[2+1] = (unsigned long)arg1; \ 2593 _argvec[2+2] = (unsigned long)arg2; \ 2594 _argvec[2+3] = (unsigned long)arg3; \ 2595 _argvec[2+4] = (unsigned long)arg4; \ 2596 __asm__ volatile( \ 2597 "mr 11,%1\n\t" \ 2598 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 2599 "stw 2,-8(11)\n\t" /* save tocptr */ \ 2600 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 2601 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 2602 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 2603 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 2604 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 2605 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 2606 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2607 "mr 11,%1\n\t" \ 2608 "mr %0,3\n\t" \ 2609 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 2610 VG_CONTRACT_FRAME_BY(512) \ 2611 : /*out*/ "=r" (_res) \ 2612 : /*in*/ "r" (&_argvec[2]) \ 2613 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2614 ); \ 2615 lval = (__typeof__(lval)) _res; \ 2616 } while (0) 2617 2618#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 2619 do { \ 2620 volatile OrigFn _orig = (orig); \ 2621 volatile unsigned long _argvec[3+5]; \ 2622 volatile unsigned long _res; \ 2623 /* _argvec[0] holds current r2 across the call */ \ 2624 _argvec[1] = (unsigned long)_orig.r2; \ 2625 _argvec[2] = (unsigned long)_orig.nraddr; \ 2626 _argvec[2+1] = (unsigned long)arg1; \ 2627 _argvec[2+2] = (unsigned long)arg2; \ 2628 _argvec[2+3] = (unsigned long)arg3; \ 2629 _argvec[2+4] = (unsigned long)arg4; \ 2630 _argvec[2+5] = (unsigned long)arg5; \ 2631 __asm__ volatile( \ 2632 "mr 11,%1\n\t" \ 2633 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 2634 "stw 2,-8(11)\n\t" /* save tocptr */ \ 2635 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 2636 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 2637 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 2638 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 2639 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 2640 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 2641 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 2642 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2643 "mr 11,%1\n\t" \ 2644 "mr %0,3\n\t" \ 2645 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 2646 VG_CONTRACT_FRAME_BY(512) \ 2647 : /*out*/ "=r" (_res) \ 2648 : /*in*/ "r" (&_argvec[2]) \ 2649 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2650 ); \ 2651 lval = (__typeof__(lval)) _res; \ 2652 } while (0) 2653 2654#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 2655 do { \ 2656 volatile OrigFn _orig = (orig); \ 2657 volatile unsigned long _argvec[3+6]; \ 2658 volatile unsigned long _res; \ 2659 /* _argvec[0] holds current r2 across the call */ \ 2660 _argvec[1] = (unsigned long)_orig.r2; \ 2661 _argvec[2] = (unsigned long)_orig.nraddr; \ 2662 _argvec[2+1] = (unsigned long)arg1; \ 2663 _argvec[2+2] = (unsigned long)arg2; \ 2664 _argvec[2+3] = (unsigned long)arg3; \ 2665 _argvec[2+4] = (unsigned long)arg4; \ 2666 _argvec[2+5] = (unsigned long)arg5; \ 2667 _argvec[2+6] = (unsigned long)arg6; \ 2668 __asm__ volatile( \ 2669 "mr 11,%1\n\t" \ 2670 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 2671 "stw 2,-8(11)\n\t" /* save tocptr */ \ 2672 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 2673 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 2674 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 2675 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 2676 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 2677 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 2678 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 2679 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 2680 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2681 "mr 11,%1\n\t" \ 2682 "mr %0,3\n\t" \ 2683 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 2684 VG_CONTRACT_FRAME_BY(512) \ 2685 : /*out*/ "=r" (_res) \ 2686 : /*in*/ "r" (&_argvec[2]) \ 2687 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2688 ); \ 2689 lval = (__typeof__(lval)) _res; \ 2690 } while (0) 2691 2692#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2693 arg7) \ 2694 do { \ 2695 volatile OrigFn _orig = (orig); \ 2696 volatile unsigned long _argvec[3+7]; \ 2697 volatile unsigned long _res; \ 2698 /* _argvec[0] holds current r2 across the call */ \ 2699 _argvec[1] = (unsigned long)_orig.r2; \ 2700 _argvec[2] = (unsigned long)_orig.nraddr; \ 2701 _argvec[2+1] = (unsigned long)arg1; \ 2702 _argvec[2+2] = (unsigned long)arg2; \ 2703 _argvec[2+3] = (unsigned long)arg3; \ 2704 _argvec[2+4] = (unsigned long)arg4; \ 2705 _argvec[2+5] = (unsigned long)arg5; \ 2706 _argvec[2+6] = (unsigned long)arg6; \ 2707 _argvec[2+7] = (unsigned long)arg7; \ 2708 __asm__ volatile( \ 2709 "mr 11,%1\n\t" \ 2710 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 2711 "stw 2,-8(11)\n\t" /* save tocptr */ \ 2712 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 2713 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 2714 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 2715 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 2716 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 2717 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 2718 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 2719 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ 2720 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 2721 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2722 "mr 11,%1\n\t" \ 2723 "mr %0,3\n\t" \ 2724 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 2725 VG_CONTRACT_FRAME_BY(512) \ 2726 : /*out*/ "=r" (_res) \ 2727 : /*in*/ "r" (&_argvec[2]) \ 2728 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2729 ); \ 2730 lval = (__typeof__(lval)) _res; \ 2731 } while (0) 2732 2733#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2734 arg7,arg8) \ 2735 do { \ 2736 volatile OrigFn _orig = (orig); \ 2737 volatile unsigned long _argvec[3+8]; \ 2738 volatile unsigned long _res; \ 2739 /* _argvec[0] holds current r2 across the call */ \ 2740 _argvec[1] = (unsigned long)_orig.r2; \ 2741 _argvec[2] = (unsigned long)_orig.nraddr; \ 2742 _argvec[2+1] = (unsigned long)arg1; \ 2743 _argvec[2+2] = (unsigned long)arg2; \ 2744 _argvec[2+3] = (unsigned long)arg3; \ 2745 _argvec[2+4] = (unsigned long)arg4; \ 2746 _argvec[2+5] = (unsigned long)arg5; \ 2747 _argvec[2+6] = (unsigned long)arg6; \ 2748 _argvec[2+7] = (unsigned long)arg7; \ 2749 _argvec[2+8] = (unsigned long)arg8; \ 2750 __asm__ volatile( \ 2751 "mr 11,%1\n\t" \ 2752 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 2753 "stw 2,-8(11)\n\t" /* save tocptr */ \ 2754 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 2755 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 2756 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 2757 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 2758 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 2759 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 2760 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 2761 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ 2762 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ 2763 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 2764 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2765 "mr 11,%1\n\t" \ 2766 "mr %0,3\n\t" \ 2767 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 2768 VG_CONTRACT_FRAME_BY(512) \ 2769 : /*out*/ "=r" (_res) \ 2770 : /*in*/ "r" (&_argvec[2]) \ 2771 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2772 ); \ 2773 lval = (__typeof__(lval)) _res; \ 2774 } while (0) 2775 2776#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2777 arg7,arg8,arg9) \ 2778 do { \ 2779 volatile OrigFn _orig = (orig); \ 2780 volatile unsigned long _argvec[3+9]; \ 2781 volatile unsigned long _res; \ 2782 /* _argvec[0] holds current r2 across the call */ \ 2783 _argvec[1] = (unsigned long)_orig.r2; \ 2784 _argvec[2] = (unsigned long)_orig.nraddr; \ 2785 _argvec[2+1] = (unsigned long)arg1; \ 2786 _argvec[2+2] = (unsigned long)arg2; \ 2787 _argvec[2+3] = (unsigned long)arg3; \ 2788 _argvec[2+4] = (unsigned long)arg4; \ 2789 _argvec[2+5] = (unsigned long)arg5; \ 2790 _argvec[2+6] = (unsigned long)arg6; \ 2791 _argvec[2+7] = (unsigned long)arg7; \ 2792 _argvec[2+8] = (unsigned long)arg8; \ 2793 _argvec[2+9] = (unsigned long)arg9; \ 2794 __asm__ volatile( \ 2795 "mr 11,%1\n\t" \ 2796 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 2797 "stw 2,-8(11)\n\t" /* save tocptr */ \ 2798 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 2799 VG_EXPAND_FRAME_BY_trashes_r3(64) \ 2800 /* arg9 */ \ 2801 "lwz 3,36(11)\n\t" \ 2802 "stw 3,56(1)\n\t" \ 2803 /* args1-8 */ \ 2804 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 2805 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 2806 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 2807 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 2808 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 2809 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 2810 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ 2811 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ 2812 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 2813 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2814 "mr 11,%1\n\t" \ 2815 "mr %0,3\n\t" \ 2816 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 2817 VG_CONTRACT_FRAME_BY(64) \ 2818 VG_CONTRACT_FRAME_BY(512) \ 2819 : /*out*/ "=r" (_res) \ 2820 : /*in*/ "r" (&_argvec[2]) \ 2821 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2822 ); \ 2823 lval = (__typeof__(lval)) _res; \ 2824 } while (0) 2825 2826#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2827 arg7,arg8,arg9,arg10) \ 2828 do { \ 2829 volatile OrigFn _orig = (orig); \ 2830 volatile unsigned long _argvec[3+10]; \ 2831 volatile unsigned long _res; \ 2832 /* _argvec[0] holds current r2 across the call */ \ 2833 _argvec[1] = (unsigned long)_orig.r2; \ 2834 _argvec[2] = (unsigned long)_orig.nraddr; \ 2835 _argvec[2+1] = (unsigned long)arg1; \ 2836 _argvec[2+2] = (unsigned long)arg2; \ 2837 _argvec[2+3] = (unsigned long)arg3; \ 2838 _argvec[2+4] = (unsigned long)arg4; \ 2839 _argvec[2+5] = (unsigned long)arg5; \ 2840 _argvec[2+6] = (unsigned long)arg6; \ 2841 _argvec[2+7] = (unsigned long)arg7; \ 2842 _argvec[2+8] = (unsigned long)arg8; \ 2843 _argvec[2+9] = (unsigned long)arg9; \ 2844 _argvec[2+10] = (unsigned long)arg10; \ 2845 __asm__ volatile( \ 2846 "mr 11,%1\n\t" \ 2847 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 2848 "stw 2,-8(11)\n\t" /* save tocptr */ \ 2849 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 2850 VG_EXPAND_FRAME_BY_trashes_r3(64) \ 2851 /* arg10 */ \ 2852 "lwz 3,40(11)\n\t" \ 2853 "stw 3,60(1)\n\t" \ 2854 /* arg9 */ \ 2855 "lwz 3,36(11)\n\t" \ 2856 "stw 3,56(1)\n\t" \ 2857 /* args1-8 */ \ 2858 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 2859 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 2860 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 2861 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 2862 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 2863 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 2864 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ 2865 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ 2866 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 2867 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2868 "mr 11,%1\n\t" \ 2869 "mr %0,3\n\t" \ 2870 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 2871 VG_CONTRACT_FRAME_BY(64) \ 2872 VG_CONTRACT_FRAME_BY(512) \ 2873 : /*out*/ "=r" (_res) \ 2874 : /*in*/ "r" (&_argvec[2]) \ 2875 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2876 ); \ 2877 lval = (__typeof__(lval)) _res; \ 2878 } while (0) 2879 2880#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2881 arg7,arg8,arg9,arg10,arg11) \ 2882 do { \ 2883 volatile OrigFn _orig = (orig); \ 2884 volatile unsigned long _argvec[3+11]; \ 2885 volatile unsigned long _res; \ 2886 /* _argvec[0] holds current r2 across the call */ \ 2887 _argvec[1] = (unsigned long)_orig.r2; \ 2888 _argvec[2] = (unsigned long)_orig.nraddr; \ 2889 _argvec[2+1] = (unsigned long)arg1; \ 2890 _argvec[2+2] = (unsigned long)arg2; \ 2891 _argvec[2+3] = (unsigned long)arg3; \ 2892 _argvec[2+4] = (unsigned long)arg4; \ 2893 _argvec[2+5] = (unsigned long)arg5; \ 2894 _argvec[2+6] = (unsigned long)arg6; \ 2895 _argvec[2+7] = (unsigned long)arg7; \ 2896 _argvec[2+8] = (unsigned long)arg8; \ 2897 _argvec[2+9] = (unsigned long)arg9; \ 2898 _argvec[2+10] = (unsigned long)arg10; \ 2899 _argvec[2+11] = (unsigned long)arg11; \ 2900 __asm__ volatile( \ 2901 "mr 11,%1\n\t" \ 2902 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 2903 "stw 2,-8(11)\n\t" /* save tocptr */ \ 2904 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 2905 VG_EXPAND_FRAME_BY_trashes_r3(72) \ 2906 /* arg11 */ \ 2907 "lwz 3,44(11)\n\t" \ 2908 "stw 3,64(1)\n\t" \ 2909 /* arg10 */ \ 2910 "lwz 3,40(11)\n\t" \ 2911 "stw 3,60(1)\n\t" \ 2912 /* arg9 */ \ 2913 "lwz 3,36(11)\n\t" \ 2914 "stw 3,56(1)\n\t" \ 2915 /* args1-8 */ \ 2916 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 2917 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 2918 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 2919 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 2920 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 2921 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 2922 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ 2923 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ 2924 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 2925 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2926 "mr 11,%1\n\t" \ 2927 "mr %0,3\n\t" \ 2928 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 2929 VG_CONTRACT_FRAME_BY(72) \ 2930 VG_CONTRACT_FRAME_BY(512) \ 2931 : /*out*/ "=r" (_res) \ 2932 : /*in*/ "r" (&_argvec[2]) \ 2933 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2934 ); \ 2935 lval = (__typeof__(lval)) _res; \ 2936 } while (0) 2937 2938#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2939 arg7,arg8,arg9,arg10,arg11,arg12) \ 2940 do { \ 2941 volatile OrigFn _orig = (orig); \ 2942 volatile unsigned long _argvec[3+12]; \ 2943 volatile unsigned long _res; \ 2944 /* _argvec[0] holds current r2 across the call */ \ 2945 _argvec[1] = (unsigned long)_orig.r2; \ 2946 _argvec[2] = (unsigned long)_orig.nraddr; \ 2947 _argvec[2+1] = (unsigned long)arg1; \ 2948 _argvec[2+2] = (unsigned long)arg2; \ 2949 _argvec[2+3] = (unsigned long)arg3; \ 2950 _argvec[2+4] = (unsigned long)arg4; \ 2951 _argvec[2+5] = (unsigned long)arg5; \ 2952 _argvec[2+6] = (unsigned long)arg6; \ 2953 _argvec[2+7] = (unsigned long)arg7; \ 2954 _argvec[2+8] = (unsigned long)arg8; \ 2955 _argvec[2+9] = (unsigned long)arg9; \ 2956 _argvec[2+10] = (unsigned long)arg10; \ 2957 _argvec[2+11] = (unsigned long)arg11; \ 2958 _argvec[2+12] = (unsigned long)arg12; \ 2959 __asm__ volatile( \ 2960 "mr 11,%1\n\t" \ 2961 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 2962 "stw 2,-8(11)\n\t" /* save tocptr */ \ 2963 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 2964 VG_EXPAND_FRAME_BY_trashes_r3(72) \ 2965 /* arg12 */ \ 2966 "lwz 3,48(11)\n\t" \ 2967 "stw 3,68(1)\n\t" \ 2968 /* arg11 */ \ 2969 "lwz 3,44(11)\n\t" \ 2970 "stw 3,64(1)\n\t" \ 2971 /* arg10 */ \ 2972 "lwz 3,40(11)\n\t" \ 2973 "stw 3,60(1)\n\t" \ 2974 /* arg9 */ \ 2975 "lwz 3,36(11)\n\t" \ 2976 "stw 3,56(1)\n\t" \ 2977 /* args1-8 */ \ 2978 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 2979 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 2980 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 2981 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 2982 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 2983 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 2984 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ 2985 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ 2986 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 2987 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2988 "mr 11,%1\n\t" \ 2989 "mr %0,3\n\t" \ 2990 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 2991 VG_CONTRACT_FRAME_BY(72) \ 2992 VG_CONTRACT_FRAME_BY(512) \ 2993 : /*out*/ "=r" (_res) \ 2994 : /*in*/ "r" (&_argvec[2]) \ 2995 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2996 ); \ 2997 lval = (__typeof__(lval)) _res; \ 2998 } while (0) 2999 3000#endif /* PLAT_ppc32_aix5 */ 3001 3002/* ------------------------ ppc64-aix5 ------------------------- */ 3003 3004#if defined(PLAT_ppc64_aix5) 3005 3006/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ 3007 3008/* These regs are trashed by the hidden call. */ 3009#define __CALLER_SAVED_REGS \ 3010 "lr", "ctr", "xer", \ 3011 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ 3012 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ 3013 "r11", "r12", "r13" 3014 3015/* Expand the stack frame, copying enough info that unwinding 3016 still works. Trashes r3. */ 3017 3018#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \ 3019 "addi 1,1,-" #_n_fr "\n\t" \ 3020 "ld 3," #_n_fr "(1)\n\t" \ 3021 "std 3,0(1)\n\t" 3022 3023#define VG_CONTRACT_FRAME_BY(_n_fr) \ 3024 "addi 1,1," #_n_fr "\n\t" 3025 3026/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned 3027 long) == 8. */ 3028 3029#define CALL_FN_W_v(lval, orig) \ 3030 do { \ 3031 volatile OrigFn _orig = (orig); \ 3032 volatile unsigned long _argvec[3+0]; \ 3033 volatile unsigned long _res; \ 3034 /* _argvec[0] holds current r2 across the call */ \ 3035 _argvec[1] = (unsigned long)_orig.r2; \ 3036 _argvec[2] = (unsigned long)_orig.nraddr; \ 3037 __asm__ volatile( \ 3038 "mr 11,%1\n\t" \ 3039 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3040 "std 2,-16(11)\n\t" /* save tocptr */ \ 3041 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3042 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3043 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3044 "mr 11,%1\n\t" \ 3045 "mr %0,3\n\t" \ 3046 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3047 VG_CONTRACT_FRAME_BY(512) \ 3048 : /*out*/ "=r" (_res) \ 3049 : /*in*/ "r" (&_argvec[2]) \ 3050 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3051 ); \ 3052 lval = (__typeof__(lval)) _res; \ 3053 } while (0) 3054 3055#define CALL_FN_W_W(lval, orig, arg1) \ 3056 do { \ 3057 volatile OrigFn _orig = (orig); \ 3058 volatile unsigned long _argvec[3+1]; \ 3059 volatile unsigned long _res; \ 3060 /* _argvec[0] holds current r2 across the call */ \ 3061 _argvec[1] = (unsigned long)_orig.r2; \ 3062 _argvec[2] = (unsigned long)_orig.nraddr; \ 3063 _argvec[2+1] = (unsigned long)arg1; \ 3064 __asm__ volatile( \ 3065 "mr 11,%1\n\t" \ 3066 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3067 "std 2,-16(11)\n\t" /* save tocptr */ \ 3068 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3069 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3070 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3071 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3072 "mr 11,%1\n\t" \ 3073 "mr %0,3\n\t" \ 3074 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3075 VG_CONTRACT_FRAME_BY(512) \ 3076 : /*out*/ "=r" (_res) \ 3077 : /*in*/ "r" (&_argvec[2]) \ 3078 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3079 ); \ 3080 lval = (__typeof__(lval)) _res; \ 3081 } while (0) 3082 3083#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 3084 do { \ 3085 volatile OrigFn _orig = (orig); \ 3086 volatile unsigned long _argvec[3+2]; \ 3087 volatile unsigned long _res; \ 3088 /* _argvec[0] holds current r2 across the call */ \ 3089 _argvec[1] = (unsigned long)_orig.r2; \ 3090 _argvec[2] = (unsigned long)_orig.nraddr; \ 3091 _argvec[2+1] = (unsigned long)arg1; \ 3092 _argvec[2+2] = (unsigned long)arg2; \ 3093 __asm__ volatile( \ 3094 "mr 11,%1\n\t" \ 3095 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3096 "std 2,-16(11)\n\t" /* save tocptr */ \ 3097 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3098 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3099 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3100 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3101 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3102 "mr 11,%1\n\t" \ 3103 "mr %0,3\n\t" \ 3104 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3105 VG_CONTRACT_FRAME_BY(512) \ 3106 : /*out*/ "=r" (_res) \ 3107 : /*in*/ "r" (&_argvec[2]) \ 3108 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3109 ); \ 3110 lval = (__typeof__(lval)) _res; \ 3111 } while (0) 3112 3113#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 3114 do { \ 3115 volatile OrigFn _orig = (orig); \ 3116 volatile unsigned long _argvec[3+3]; \ 3117 volatile unsigned long _res; \ 3118 /* _argvec[0] holds current r2 across the call */ \ 3119 _argvec[1] = (unsigned long)_orig.r2; \ 3120 _argvec[2] = (unsigned long)_orig.nraddr; \ 3121 _argvec[2+1] = (unsigned long)arg1; \ 3122 _argvec[2+2] = (unsigned long)arg2; \ 3123 _argvec[2+3] = (unsigned long)arg3; \ 3124 __asm__ volatile( \ 3125 "mr 11,%1\n\t" \ 3126 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3127 "std 2,-16(11)\n\t" /* save tocptr */ \ 3128 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3129 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3130 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3131 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 3132 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3133 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3134 "mr 11,%1\n\t" \ 3135 "mr %0,3\n\t" \ 3136 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3137 VG_CONTRACT_FRAME_BY(512) \ 3138 : /*out*/ "=r" (_res) \ 3139 : /*in*/ "r" (&_argvec[2]) \ 3140 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3141 ); \ 3142 lval = (__typeof__(lval)) _res; \ 3143 } while (0) 3144 3145#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 3146 do { \ 3147 volatile OrigFn _orig = (orig); \ 3148 volatile unsigned long _argvec[3+4]; \ 3149 volatile unsigned long _res; \ 3150 /* _argvec[0] holds current r2 across the call */ \ 3151 _argvec[1] = (unsigned long)_orig.r2; \ 3152 _argvec[2] = (unsigned long)_orig.nraddr; \ 3153 _argvec[2+1] = (unsigned long)arg1; \ 3154 _argvec[2+2] = (unsigned long)arg2; \ 3155 _argvec[2+3] = (unsigned long)arg3; \ 3156 _argvec[2+4] = (unsigned long)arg4; \ 3157 __asm__ volatile( \ 3158 "mr 11,%1\n\t" \ 3159 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3160 "std 2,-16(11)\n\t" /* save tocptr */ \ 3161 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3162 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3163 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3164 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 3165 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 3166 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3167 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3168 "mr 11,%1\n\t" \ 3169 "mr %0,3\n\t" \ 3170 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3171 VG_CONTRACT_FRAME_BY(512) \ 3172 : /*out*/ "=r" (_res) \ 3173 : /*in*/ "r" (&_argvec[2]) \ 3174 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3175 ); \ 3176 lval = (__typeof__(lval)) _res; \ 3177 } while (0) 3178 3179#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 3180 do { \ 3181 volatile OrigFn _orig = (orig); \ 3182 volatile unsigned long _argvec[3+5]; \ 3183 volatile unsigned long _res; \ 3184 /* _argvec[0] holds current r2 across the call */ \ 3185 _argvec[1] = (unsigned long)_orig.r2; \ 3186 _argvec[2] = (unsigned long)_orig.nraddr; \ 3187 _argvec[2+1] = (unsigned long)arg1; \ 3188 _argvec[2+2] = (unsigned long)arg2; \ 3189 _argvec[2+3] = (unsigned long)arg3; \ 3190 _argvec[2+4] = (unsigned long)arg4; \ 3191 _argvec[2+5] = (unsigned long)arg5; \ 3192 __asm__ volatile( \ 3193 "mr 11,%1\n\t" \ 3194 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3195 "std 2,-16(11)\n\t" /* save tocptr */ \ 3196 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3197 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3198 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3199 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 3200 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 3201 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 3202 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3203 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3204 "mr 11,%1\n\t" \ 3205 "mr %0,3\n\t" \ 3206 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3207 VG_CONTRACT_FRAME_BY(512) \ 3208 : /*out*/ "=r" (_res) \ 3209 : /*in*/ "r" (&_argvec[2]) \ 3210 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3211 ); \ 3212 lval = (__typeof__(lval)) _res; \ 3213 } while (0) 3214 3215#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 3216 do { \ 3217 volatile OrigFn _orig = (orig); \ 3218 volatile unsigned long _argvec[3+6]; \ 3219 volatile unsigned long _res; \ 3220 /* _argvec[0] holds current r2 across the call */ \ 3221 _argvec[1] = (unsigned long)_orig.r2; \ 3222 _argvec[2] = (unsigned long)_orig.nraddr; \ 3223 _argvec[2+1] = (unsigned long)arg1; \ 3224 _argvec[2+2] = (unsigned long)arg2; \ 3225 _argvec[2+3] = (unsigned long)arg3; \ 3226 _argvec[2+4] = (unsigned long)arg4; \ 3227 _argvec[2+5] = (unsigned long)arg5; \ 3228 _argvec[2+6] = (unsigned long)arg6; \ 3229 __asm__ volatile( \ 3230 "mr 11,%1\n\t" \ 3231 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3232 "std 2,-16(11)\n\t" /* save tocptr */ \ 3233 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3234 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3235 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3236 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 3237 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 3238 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 3239 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 3240 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3241 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3242 "mr 11,%1\n\t" \ 3243 "mr %0,3\n\t" \ 3244 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3245 VG_CONTRACT_FRAME_BY(512) \ 3246 : /*out*/ "=r" (_res) \ 3247 : /*in*/ "r" (&_argvec[2]) \ 3248 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3249 ); \ 3250 lval = (__typeof__(lval)) _res; \ 3251 } while (0) 3252 3253#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3254 arg7) \ 3255 do { \ 3256 volatile OrigFn _orig = (orig); \ 3257 volatile unsigned long _argvec[3+7]; \ 3258 volatile unsigned long _res; \ 3259 /* _argvec[0] holds current r2 across the call */ \ 3260 _argvec[1] = (unsigned long)_orig.r2; \ 3261 _argvec[2] = (unsigned long)_orig.nraddr; \ 3262 _argvec[2+1] = (unsigned long)arg1; \ 3263 _argvec[2+2] = (unsigned long)arg2; \ 3264 _argvec[2+3] = (unsigned long)arg3; \ 3265 _argvec[2+4] = (unsigned long)arg4; \ 3266 _argvec[2+5] = (unsigned long)arg5; \ 3267 _argvec[2+6] = (unsigned long)arg6; \ 3268 _argvec[2+7] = (unsigned long)arg7; \ 3269 __asm__ volatile( \ 3270 "mr 11,%1\n\t" \ 3271 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3272 "std 2,-16(11)\n\t" /* save tocptr */ \ 3273 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3274 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3275 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3276 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 3277 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 3278 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 3279 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 3280 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 3281 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3282 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3283 "mr 11,%1\n\t" \ 3284 "mr %0,3\n\t" \ 3285 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3286 VG_CONTRACT_FRAME_BY(512) \ 3287 : /*out*/ "=r" (_res) \ 3288 : /*in*/ "r" (&_argvec[2]) \ 3289 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3290 ); \ 3291 lval = (__typeof__(lval)) _res; \ 3292 } while (0) 3293 3294#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3295 arg7,arg8) \ 3296 do { \ 3297 volatile OrigFn _orig = (orig); \ 3298 volatile unsigned long _argvec[3+8]; \ 3299 volatile unsigned long _res; \ 3300 /* _argvec[0] holds current r2 across the call */ \ 3301 _argvec[1] = (unsigned long)_orig.r2; \ 3302 _argvec[2] = (unsigned long)_orig.nraddr; \ 3303 _argvec[2+1] = (unsigned long)arg1; \ 3304 _argvec[2+2] = (unsigned long)arg2; \ 3305 _argvec[2+3] = (unsigned long)arg3; \ 3306 _argvec[2+4] = (unsigned long)arg4; \ 3307 _argvec[2+5] = (unsigned long)arg5; \ 3308 _argvec[2+6] = (unsigned long)arg6; \ 3309 _argvec[2+7] = (unsigned long)arg7; \ 3310 _argvec[2+8] = (unsigned long)arg8; \ 3311 __asm__ volatile( \ 3312 "mr 11,%1\n\t" \ 3313 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3314 "std 2,-16(11)\n\t" /* save tocptr */ \ 3315 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3316 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3317 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3318 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 3319 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 3320 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 3321 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 3322 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 3323 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 3324 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3325 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3326 "mr 11,%1\n\t" \ 3327 "mr %0,3\n\t" \ 3328 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3329 VG_CONTRACT_FRAME_BY(512) \ 3330 : /*out*/ "=r" (_res) \ 3331 : /*in*/ "r" (&_argvec[2]) \ 3332 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3333 ); \ 3334 lval = (__typeof__(lval)) _res; \ 3335 } while (0) 3336 3337#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3338 arg7,arg8,arg9) \ 3339 do { \ 3340 volatile OrigFn _orig = (orig); \ 3341 volatile unsigned long _argvec[3+9]; \ 3342 volatile unsigned long _res; \ 3343 /* _argvec[0] holds current r2 across the call */ \ 3344 _argvec[1] = (unsigned long)_orig.r2; \ 3345 _argvec[2] = (unsigned long)_orig.nraddr; \ 3346 _argvec[2+1] = (unsigned long)arg1; \ 3347 _argvec[2+2] = (unsigned long)arg2; \ 3348 _argvec[2+3] = (unsigned long)arg3; \ 3349 _argvec[2+4] = (unsigned long)arg4; \ 3350 _argvec[2+5] = (unsigned long)arg5; \ 3351 _argvec[2+6] = (unsigned long)arg6; \ 3352 _argvec[2+7] = (unsigned long)arg7; \ 3353 _argvec[2+8] = (unsigned long)arg8; \ 3354 _argvec[2+9] = (unsigned long)arg9; \ 3355 __asm__ volatile( \ 3356 "mr 11,%1\n\t" \ 3357 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3358 "std 2,-16(11)\n\t" /* save tocptr */ \ 3359 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3360 VG_EXPAND_FRAME_BY_trashes_r3(128) \ 3361 /* arg9 */ \ 3362 "ld 3,72(11)\n\t" \ 3363 "std 3,112(1)\n\t" \ 3364 /* args1-8 */ \ 3365 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3366 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3367 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 3368 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 3369 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 3370 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 3371 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 3372 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 3373 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3374 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3375 "mr 11,%1\n\t" \ 3376 "mr %0,3\n\t" \ 3377 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3378 VG_CONTRACT_FRAME_BY(128) \ 3379 VG_CONTRACT_FRAME_BY(512) \ 3380 : /*out*/ "=r" (_res) \ 3381 : /*in*/ "r" (&_argvec[2]) \ 3382 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3383 ); \ 3384 lval = (__typeof__(lval)) _res; \ 3385 } while (0) 3386 3387#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3388 arg7,arg8,arg9,arg10) \ 3389 do { \ 3390 volatile OrigFn _orig = (orig); \ 3391 volatile unsigned long _argvec[3+10]; \ 3392 volatile unsigned long _res; \ 3393 /* _argvec[0] holds current r2 across the call */ \ 3394 _argvec[1] = (unsigned long)_orig.r2; \ 3395 _argvec[2] = (unsigned long)_orig.nraddr; \ 3396 _argvec[2+1] = (unsigned long)arg1; \ 3397 _argvec[2+2] = (unsigned long)arg2; \ 3398 _argvec[2+3] = (unsigned long)arg3; \ 3399 _argvec[2+4] = (unsigned long)arg4; \ 3400 _argvec[2+5] = (unsigned long)arg5; \ 3401 _argvec[2+6] = (unsigned long)arg6; \ 3402 _argvec[2+7] = (unsigned long)arg7; \ 3403 _argvec[2+8] = (unsigned long)arg8; \ 3404 _argvec[2+9] = (unsigned long)arg9; \ 3405 _argvec[2+10] = (unsigned long)arg10; \ 3406 __asm__ volatile( \ 3407 "mr 11,%1\n\t" \ 3408 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3409 "std 2,-16(11)\n\t" /* save tocptr */ \ 3410 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3411 VG_EXPAND_FRAME_BY_trashes_r3(128) \ 3412 /* arg10 */ \ 3413 "ld 3,80(11)\n\t" \ 3414 "std 3,120(1)\n\t" \ 3415 /* arg9 */ \ 3416 "ld 3,72(11)\n\t" \ 3417 "std 3,112(1)\n\t" \ 3418 /* args1-8 */ \ 3419 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3420 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3421 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 3422 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 3423 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 3424 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 3425 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 3426 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 3427 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3428 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3429 "mr 11,%1\n\t" \ 3430 "mr %0,3\n\t" \ 3431 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3432 VG_CONTRACT_FRAME_BY(128) \ 3433 VG_CONTRACT_FRAME_BY(512) \ 3434 : /*out*/ "=r" (_res) \ 3435 : /*in*/ "r" (&_argvec[2]) \ 3436 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3437 ); \ 3438 lval = (__typeof__(lval)) _res; \ 3439 } while (0) 3440 3441#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3442 arg7,arg8,arg9,arg10,arg11) \ 3443 do { \ 3444 volatile OrigFn _orig = (orig); \ 3445 volatile unsigned long _argvec[3+11]; \ 3446 volatile unsigned long _res; \ 3447 /* _argvec[0] holds current r2 across the call */ \ 3448 _argvec[1] = (unsigned long)_orig.r2; \ 3449 _argvec[2] = (unsigned long)_orig.nraddr; \ 3450 _argvec[2+1] = (unsigned long)arg1; \ 3451 _argvec[2+2] = (unsigned long)arg2; \ 3452 _argvec[2+3] = (unsigned long)arg3; \ 3453 _argvec[2+4] = (unsigned long)arg4; \ 3454 _argvec[2+5] = (unsigned long)arg5; \ 3455 _argvec[2+6] = (unsigned long)arg6; \ 3456 _argvec[2+7] = (unsigned long)arg7; \ 3457 _argvec[2+8] = (unsigned long)arg8; \ 3458 _argvec[2+9] = (unsigned long)arg9; \ 3459 _argvec[2+10] = (unsigned long)arg10; \ 3460 _argvec[2+11] = (unsigned long)arg11; \ 3461 __asm__ volatile( \ 3462 "mr 11,%1\n\t" \ 3463 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3464 "std 2,-16(11)\n\t" /* save tocptr */ \ 3465 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3466 VG_EXPAND_FRAME_BY_trashes_r3(144) \ 3467 /* arg11 */ \ 3468 "ld 3,88(11)\n\t" \ 3469 "std 3,128(1)\n\t" \ 3470 /* arg10 */ \ 3471 "ld 3,80(11)\n\t" \ 3472 "std 3,120(1)\n\t" \ 3473 /* arg9 */ \ 3474 "ld 3,72(11)\n\t" \ 3475 "std 3,112(1)\n\t" \ 3476 /* args1-8 */ \ 3477 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3478 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3479 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 3480 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 3481 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 3482 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 3483 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 3484 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 3485 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3486 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3487 "mr 11,%1\n\t" \ 3488 "mr %0,3\n\t" \ 3489 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3490 VG_CONTRACT_FRAME_BY(144) \ 3491 VG_CONTRACT_FRAME_BY(512) \ 3492 : /*out*/ "=r" (_res) \ 3493 : /*in*/ "r" (&_argvec[2]) \ 3494 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3495 ); \ 3496 lval = (__typeof__(lval)) _res; \ 3497 } while (0) 3498 3499#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3500 arg7,arg8,arg9,arg10,arg11,arg12) \ 3501 do { \ 3502 volatile OrigFn _orig = (orig); \ 3503 volatile unsigned long _argvec[3+12]; \ 3504 volatile unsigned long _res; \ 3505 /* _argvec[0] holds current r2 across the call */ \ 3506 _argvec[1] = (unsigned long)_orig.r2; \ 3507 _argvec[2] = (unsigned long)_orig.nraddr; \ 3508 _argvec[2+1] = (unsigned long)arg1; \ 3509 _argvec[2+2] = (unsigned long)arg2; \ 3510 _argvec[2+3] = (unsigned long)arg3; \ 3511 _argvec[2+4] = (unsigned long)arg4; \ 3512 _argvec[2+5] = (unsigned long)arg5; \ 3513 _argvec[2+6] = (unsigned long)arg6; \ 3514 _argvec[2+7] = (unsigned long)arg7; \ 3515 _argvec[2+8] = (unsigned long)arg8; \ 3516 _argvec[2+9] = (unsigned long)arg9; \ 3517 _argvec[2+10] = (unsigned long)arg10; \ 3518 _argvec[2+11] = (unsigned long)arg11; \ 3519 _argvec[2+12] = (unsigned long)arg12; \ 3520 __asm__ volatile( \ 3521 "mr 11,%1\n\t" \ 3522 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3523 "std 2,-16(11)\n\t" /* save tocptr */ \ 3524 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3525 VG_EXPAND_FRAME_BY_trashes_r3(144) \ 3526 /* arg12 */ \ 3527 "ld 3,96(11)\n\t" \ 3528 "std 3,136(1)\n\t" \ 3529 /* arg11 */ \ 3530 "ld 3,88(11)\n\t" \ 3531 "std 3,128(1)\n\t" \ 3532 /* arg10 */ \ 3533 "ld 3,80(11)\n\t" \ 3534 "std 3,120(1)\n\t" \ 3535 /* arg9 */ \ 3536 "ld 3,72(11)\n\t" \ 3537 "std 3,112(1)\n\t" \ 3538 /* args1-8 */ \ 3539 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3540 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3541 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 3542 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 3543 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 3544 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 3545 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 3546 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 3547 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3548 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3549 "mr 11,%1\n\t" \ 3550 "mr %0,3\n\t" \ 3551 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3552 VG_CONTRACT_FRAME_BY(144) \ 3553 VG_CONTRACT_FRAME_BY(512) \ 3554 : /*out*/ "=r" (_res) \ 3555 : /*in*/ "r" (&_argvec[2]) \ 3556 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3557 ); \ 3558 lval = (__typeof__(lval)) _res; \ 3559 } while (0) 3560 3561#endif /* PLAT_ppc64_aix5 */ 3562 3563 3564/* ------------------------------------------------------------------ */ 3565/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */ 3566/* */ 3567/* ------------------------------------------------------------------ */ 3568 3569/* Some request codes. There are many more of these, but most are not 3570 exposed to end-user view. These are the public ones, all of the 3571 form 0x1000 + small_number. 3572 3573 Core ones are in the range 0x00000000--0x0000ffff. The non-public 3574 ones start at 0x2000. 3575*/ 3576 3577/* These macros are used by tools -- they must be public, but don't 3578 embed them into other programs. */ 3579#define VG_USERREQ_TOOL_BASE(a,b) \ 3580 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16)) 3581#define VG_IS_TOOL_USERREQ(a, b, v) \ 3582 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000)) 3583 3584/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! 3585 This enum comprises an ABI exported by Valgrind to programs 3586 which use client requests. DO NOT CHANGE THE ORDER OF THESE 3587 ENTRIES, NOR DELETE ANY -- add new ones at the end. */ 3588typedef 3589 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001, 3590 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002, 3591 3592 /* These allow any function to be called from the simulated 3593 CPU but run on the real CPU. Nb: the first arg passed to 3594 the function is always the ThreadId of the running 3595 thread! So CLIENT_CALL0 actually requires a 1 arg 3596 function, etc. */ 3597 VG_USERREQ__CLIENT_CALL0 = 0x1101, 3598 VG_USERREQ__CLIENT_CALL1 = 0x1102, 3599 VG_USERREQ__CLIENT_CALL2 = 0x1103, 3600 VG_USERREQ__CLIENT_CALL3 = 0x1104, 3601 3602 /* Can be useful in regression testing suites -- eg. can 3603 send Valgrind's output to /dev/null and still count 3604 errors. */ 3605 VG_USERREQ__COUNT_ERRORS = 0x1201, 3606 3607 /* These are useful and can be interpreted by any tool that 3608 tracks malloc() et al, by using vg_replace_malloc.c. */ 3609 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301, 3610 VG_USERREQ__FREELIKE_BLOCK = 0x1302, 3611 /* Memory pool support. */ 3612 VG_USERREQ__CREATE_MEMPOOL = 0x1303, 3613 VG_USERREQ__DESTROY_MEMPOOL = 0x1304, 3614 VG_USERREQ__MEMPOOL_ALLOC = 0x1305, 3615 VG_USERREQ__MEMPOOL_FREE = 0x1306, 3616 VG_USERREQ__MEMPOOL_TRIM = 0x1307, 3617 VG_USERREQ__MOVE_MEMPOOL = 0x1308, 3618 VG_USERREQ__MEMPOOL_CHANGE = 0x1309, 3619 VG_USERREQ__MEMPOOL_EXISTS = 0x130a, 3620 3621 /* Allow printfs to valgrind log. */ 3622 VG_USERREQ__PRINTF = 0x1401, 3623 VG_USERREQ__PRINTF_BACKTRACE = 0x1402, 3624 3625 /* Stack support. */ 3626 VG_USERREQ__STACK_REGISTER = 0x1501, 3627 VG_USERREQ__STACK_DEREGISTER = 0x1502, 3628 VG_USERREQ__STACK_CHANGE = 0x1503, 3629 3630 /* Wine support */ 3631 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601 3632 } Vg_ClientRequest; 3633 3634#if !defined(__GNUC__) 3635# define __extension__ /* */ 3636#endif 3637 3638/* Returns the number of Valgrinds this code is running under. That 3639 is, 0 if running natively, 1 if running under Valgrind, 2 if 3640 running under Valgrind which is running under another Valgrind, 3641 etc. */ 3642#define RUNNING_ON_VALGRIND __extension__ \ 3643 ({unsigned int _qzz_res; \ 3644 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \ 3645 VG_USERREQ__RUNNING_ON_VALGRIND, \ 3646 0, 0, 0, 0, 0); \ 3647 _qzz_res; \ 3648 }) 3649 3650 3651/* Discard translation of code in the range [_qzz_addr .. _qzz_addr + 3652 _qzz_len - 1]. Useful if you are debugging a JITter or some such, 3653 since it provides a way to make sure valgrind will retranslate the 3654 invalidated area. Returns no value. */ 3655#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \ 3656 {unsigned int _qzz_res; \ 3657 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 3658 VG_USERREQ__DISCARD_TRANSLATIONS, \ 3659 _qzz_addr, _qzz_len, 0, 0, 0); \ 3660 } 3661 3662 3663/* These requests are for getting Valgrind itself to print something. 3664 Possibly with a backtrace. This is a really ugly hack. */ 3665 3666#if defined(NVALGRIND) 3667 3668# define VALGRIND_PRINTF(...) 3669# define VALGRIND_PRINTF_BACKTRACE(...) 3670 3671#else /* NVALGRIND */ 3672 3673/* Modern GCC will optimize the static routine out if unused, 3674 and unused attribute will shut down warnings about it. */ 3675static int VALGRIND_PRINTF(const char *format, ...) 3676 __attribute__((format(__printf__, 1, 2), __unused__)); 3677static int 3678VALGRIND_PRINTF(const char *format, ...) 3679{ 3680 unsigned long _qzz_res; 3681 va_list vargs; 3682 va_start(vargs, format); 3683 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF, 3684 (unsigned long)format, (unsigned long)vargs, 3685 0, 0, 0); 3686 va_end(vargs); 3687 return (int)_qzz_res; 3688} 3689 3690static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...) 3691 __attribute__((format(__printf__, 1, 2), __unused__)); 3692static int 3693VALGRIND_PRINTF_BACKTRACE(const char *format, ...) 3694{ 3695 unsigned long _qzz_res; 3696 va_list vargs; 3697 va_start(vargs, format); 3698 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE, 3699 (unsigned long)format, (unsigned long)vargs, 3700 0, 0, 0); 3701 va_end(vargs); 3702 return (int)_qzz_res; 3703} 3704 3705#endif /* NVALGRIND */ 3706 3707 3708/* These requests allow control to move from the simulated CPU to the 3709 real CPU, calling an arbitary function. 3710 3711 Note that the current ThreadId is inserted as the first argument. 3712 So this call: 3713 3714 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2) 3715 3716 requires f to have this signature: 3717 3718 Word f(Word tid, Word arg1, Word arg2) 3719 3720 where "Word" is a word-sized type. 3721 3722 Note that these client requests are not entirely reliable. For example, 3723 if you call a function with them that subsequently calls printf(), 3724 there's a high chance Valgrind will crash. Generally, your prospects of 3725 these working are made higher if the called function does not refer to 3726 any global variables, and does not refer to any libc or other functions 3727 (printf et al). Any kind of entanglement with libc or dynamic linking is 3728 likely to have a bad outcome, for tricky reasons which we've grappled 3729 with a lot in the past. 3730*/ 3731#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \ 3732 __extension__ \ 3733 ({unsigned long _qyy_res; \ 3734 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ 3735 VG_USERREQ__CLIENT_CALL0, \ 3736 _qyy_fn, \ 3737 0, 0, 0, 0); \ 3738 _qyy_res; \ 3739 }) 3740 3741#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \ 3742 __extension__ \ 3743 ({unsigned long _qyy_res; \ 3744 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ 3745 VG_USERREQ__CLIENT_CALL1, \ 3746 _qyy_fn, \ 3747 _qyy_arg1, 0, 0, 0); \ 3748 _qyy_res; \ 3749 }) 3750 3751#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \ 3752 __extension__ \ 3753 ({unsigned long _qyy_res; \ 3754 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ 3755 VG_USERREQ__CLIENT_CALL2, \ 3756 _qyy_fn, \ 3757 _qyy_arg1, _qyy_arg2, 0, 0); \ 3758 _qyy_res; \ 3759 }) 3760 3761#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \ 3762 __extension__ \ 3763 ({unsigned long _qyy_res; \ 3764 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ 3765 VG_USERREQ__CLIENT_CALL3, \ 3766 _qyy_fn, \ 3767 _qyy_arg1, _qyy_arg2, \ 3768 _qyy_arg3, 0); \ 3769 _qyy_res; \ 3770 }) 3771 3772 3773/* Counts the number of errors that have been recorded by a tool. Nb: 3774 the tool must record the errors with VG_(maybe_record_error)() or 3775 VG_(unique_error)() for them to be counted. */ 3776#define VALGRIND_COUNT_ERRORS \ 3777 __extension__ \ 3778 ({unsigned int _qyy_res; \ 3779 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ 3780 VG_USERREQ__COUNT_ERRORS, \ 3781 0, 0, 0, 0, 0); \ 3782 _qyy_res; \ 3783 }) 3784 3785/* Mark a block of memory as having been allocated by a malloc()-like 3786 function. `addr' is the start of the usable block (ie. after any 3787 redzone) `rzB' is redzone size if the allocator can apply redzones; 3788 use '0' if not. Adding redzones makes it more likely Valgrind will spot 3789 block overruns. `is_zeroed' indicates if the memory is zeroed, as it is 3790 for calloc(). Put it immediately after the point where a block is 3791 allocated. 3792 3793 If you're using Memcheck: If you're allocating memory via superblocks, 3794 and then handing out small chunks of each superblock, if you don't have 3795 redzones on your small blocks, it's worth marking the superblock with 3796 VALGRIND_MAKE_MEM_NOACCESS when it's created, so that block overruns are 3797 detected. But if you can put redzones on, it's probably better to not do 3798 this, so that messages for small overruns are described in terms of the 3799 small block rather than the superblock (but if you have a big overrun 3800 that skips over a redzone, you could miss an error this way). See 3801 memcheck/tests/custom_alloc.c for an example. 3802 3803 WARNING: if your allocator uses malloc() or 'new' to allocate 3804 superblocks, rather than mmap() or brk(), this will not work properly -- 3805 you'll likely get assertion failures during leak detection. This is 3806 because Valgrind doesn't like seeing overlapping heap blocks. Sorry. 3807 3808 Nb: block must be freed via a free()-like function specified 3809 with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */ 3810#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ 3811 {unsigned int _qzz_res; \ 3812 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 3813 VG_USERREQ__MALLOCLIKE_BLOCK, \ 3814 addr, sizeB, rzB, is_zeroed, 0); \ 3815 } 3816 3817/* Mark a block of memory as having been freed by a free()-like function. 3818 `rzB' is redzone size; it must match that given to 3819 VALGRIND_MALLOCLIKE_BLOCK. Memory not freed will be detected by the leak 3820 checker. Put it immediately after the point where the block is freed. */ 3821#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \ 3822 {unsigned int _qzz_res; \ 3823 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 3824 VG_USERREQ__FREELIKE_BLOCK, \ 3825 addr, rzB, 0, 0, 0); \ 3826 } 3827 3828/* Create a memory pool. */ 3829#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \ 3830 {unsigned int _qzz_res; \ 3831 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 3832 VG_USERREQ__CREATE_MEMPOOL, \ 3833 pool, rzB, is_zeroed, 0, 0); \ 3834 } 3835 3836/* Destroy a memory pool. */ 3837#define VALGRIND_DESTROY_MEMPOOL(pool) \ 3838 {unsigned int _qzz_res; \ 3839 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 3840 VG_USERREQ__DESTROY_MEMPOOL, \ 3841 pool, 0, 0, 0, 0); \ 3842 } 3843 3844/* Associate a piece of memory with a memory pool. */ 3845#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \ 3846 {unsigned int _qzz_res; \ 3847 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 3848 VG_USERREQ__MEMPOOL_ALLOC, \ 3849 pool, addr, size, 0, 0); \ 3850 } 3851 3852/* Disassociate a piece of memory from a memory pool. */ 3853#define VALGRIND_MEMPOOL_FREE(pool, addr) \ 3854 {unsigned int _qzz_res; \ 3855 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 3856 VG_USERREQ__MEMPOOL_FREE, \ 3857 pool, addr, 0, 0, 0); \ 3858 } 3859 3860/* Disassociate any pieces outside a particular range. */ 3861#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \ 3862 {unsigned int _qzz_res; \ 3863 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 3864 VG_USERREQ__MEMPOOL_TRIM, \ 3865 pool, addr, size, 0, 0); \ 3866 } 3867 3868/* Resize and/or move a piece associated with a memory pool. */ 3869#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \ 3870 {unsigned int _qzz_res; \ 3871 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 3872 VG_USERREQ__MOVE_MEMPOOL, \ 3873 poolA, poolB, 0, 0, 0); \ 3874 } 3875 3876/* Resize and/or move a piece associated with a memory pool. */ 3877#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \ 3878 {unsigned int _qzz_res; \ 3879 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 3880 VG_USERREQ__MEMPOOL_CHANGE, \ 3881 pool, addrA, addrB, size, 0); \ 3882 } 3883 3884/* Return 1 if a mempool exists, else 0. */ 3885#define VALGRIND_MEMPOOL_EXISTS(pool) \ 3886 __extension__ \ 3887 ({unsigned int _qzz_res; \ 3888 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 3889 VG_USERREQ__MEMPOOL_EXISTS, \ 3890 pool, 0, 0, 0, 0); \ 3891 _qzz_res; \ 3892 }) 3893 3894/* Mark a piece of memory as being a stack. Returns a stack id. */ 3895#define VALGRIND_STACK_REGISTER(start, end) \ 3896 __extension__ \ 3897 ({unsigned int _qzz_res; \ 3898 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 3899 VG_USERREQ__STACK_REGISTER, \ 3900 start, end, 0, 0, 0); \ 3901 _qzz_res; \ 3902 }) 3903 3904/* Unmark the piece of memory associated with a stack id as being a 3905 stack. */ 3906#define VALGRIND_STACK_DEREGISTER(id) \ 3907 {unsigned int _qzz_res; \ 3908 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 3909 VG_USERREQ__STACK_DEREGISTER, \ 3910 id, 0, 0, 0, 0); \ 3911 } 3912 3913/* Change the start and end address of the stack id. */ 3914#define VALGRIND_STACK_CHANGE(id, start, end) \ 3915 {unsigned int _qzz_res; \ 3916 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 3917 VG_USERREQ__STACK_CHANGE, \ 3918 id, start, end, 0, 0); \ 3919 } 3920 3921/* Load PDB debug info for Wine PE image_map. */ 3922#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \ 3923 {unsigned int _qzz_res; \ 3924 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 3925 VG_USERREQ__LOAD_PDB_DEBUGINFO, \ 3926 fd, ptr, total_size, delta, 0); \ 3927 } 3928 3929 3930#undef PLAT_x86_linux 3931#undef PLAT_amd64_linux 3932#undef PLAT_ppc32_linux 3933#undef PLAT_ppc64_linux 3934#undef PLAT_ppc32_aix5 3935#undef PLAT_ppc64_aix5 3936 3937#endif /* __VALGRIND_H */ 3938