valgrind.h revision c8259b85b701d25d72aabe9dc0a8154517f96913
1ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe/* -*- c -*- 2da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe ---------------------------------------------------------------- 3da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe 4da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe Notice that the following BSD-style license applies to this one 5da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe file (valgrind.h) only. The rest of Valgrind is licensed under the 6ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe terms of the GNU General Public License, version 2, unless 7ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe otherwise indicated. See the COPYING file in the source 8ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe distribution for details. 9ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe 10ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe ---------------------------------------------------------------- 11ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe 12ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe This file is part of Valgrind, a dynamic binary instrumentation 13ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe framework. 14ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe 155fdd124a3b811993542825847f207587d5f4661eJens Axboe Copyright (C) 2000-2009 Julian Seward. All rights reserved. 167292056a38857ded6f7a64f11d14d642772c31bdJens Axboe 170fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe Redistribution and use in source and binary forms, with or without 187292056a38857ded6f7a64f11d14d642772c31bdJens Axboe modification, are permitted provided that the following conditions 190fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe are met: 20ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe 21ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe 1. Redistributions of source code must retain the above copyright 22ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe notice, this list of conditions and the following disclaimer. 23b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe 24b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe 2. The origin of this software must not be misrepresented; you must 259cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe not claim that you wrote the original software. If you use this 269cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe software in a product, an acknowledgment in the product 27b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe documentation would be appreciated but is not required. 280fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe 29b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe 3. Altered source versions must be plainly marked as such, and must 30ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe not be misrepresented as being the original software. 31de890a1e48d40238dac69f302708dde8719de240Steven Lang 32de890a1e48d40238dac69f302708dde8719de240Steven Lang 4. The name of the author may not be used to endorse or promote 33de890a1e48d40238dac69f302708dde8719de240Steven Lang products derived from this software without specific prior written 34de890a1e48d40238dac69f302708dde8719de240Steven Lang permission. 35de890a1e48d40238dac69f302708dde8719de240Steven Lang 366f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 37de890a1e48d40238dac69f302708dde8719de240Steven Lang OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 38de890a1e48d40238dac69f302708dde8719de240Steven Lang WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 39664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 40664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 41664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 42664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 43664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 44664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 45664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 46b96d243044023b28731341d290943b5d47a5f794Jens Axboe SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 47b96d243044023b28731341d290943b5d47a5f794Jens Axboe 480fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe ---------------------------------------------------------------- 490fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe 500fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe Notice that the above BSD-style license applies to this one file 510fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe (valgrind.h) only. The entire rest of Valgrind is licensed under 52664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe the terms of the GNU General Public License, version 2. See the 53664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe COPYING file in the source distribution for details. 54de890a1e48d40238dac69f302708dde8719de240Steven Lang 55de890a1e48d40238dac69f302708dde8719de240Steven Lang ---------------------------------------------------------------- 56de890a1e48d40238dac69f302708dde8719de240Steven Lang*/ 57de890a1e48d40238dac69f302708dde8719de240Steven Lang 58de890a1e48d40238dac69f302708dde8719de240Steven Lang 59de890a1e48d40238dac69f302708dde8719de240Steven Lang/* This file is for inclusion into client (your!) code. 60de890a1e48d40238dac69f302708dde8719de240Steven Lang 61de890a1e48d40238dac69f302708dde8719de240Steven Lang You can use these macros to manipulate and query Valgrind's 62de890a1e48d40238dac69f302708dde8719de240Steven Lang execution inside your own programs. 63de890a1e48d40238dac69f302708dde8719de240Steven Lang 64de890a1e48d40238dac69f302708dde8719de240Steven Lang The resulting executables will still run without Valgrind, just a 65de890a1e48d40238dac69f302708dde8719de240Steven Lang little bit more slowly than they otherwise would, but otherwise 66de890a1e48d40238dac69f302708dde8719de240Steven Lang unchanged. When not running on valgrind, each client request 67de890a1e48d40238dac69f302708dde8719de240Steven Lang consumes very few (eg. 7) instructions, so the resulting performance 68de890a1e48d40238dac69f302708dde8719de240Steven Lang loss is negligible unless you plan to execute client requests 69de890a1e48d40238dac69f302708dde8719de240Steven Lang millions of times per second. Nevertheless, if that is still a 70de890a1e48d40238dac69f302708dde8719de240Steven Lang problem, you can compile with the NVALGRIND symbol defined (gcc 71de890a1e48d40238dac69f302708dde8719de240Steven Lang -DNVALGRIND) so that client requests are not even compiled in. */ 72de890a1e48d40238dac69f302708dde8719de240Steven Lang 73de890a1e48d40238dac69f302708dde8719de240Steven Lang#ifndef __VALGRIND_H 74de890a1e48d40238dac69f302708dde8719de240Steven Lang#define __VALGRIND_H 75de890a1e48d40238dac69f302708dde8719de240Steven Lang 76de890a1e48d40238dac69f302708dde8719de240Steven Lang#include <stdarg.h> 77de890a1e48d40238dac69f302708dde8719de240Steven Lang 78de890a1e48d40238dac69f302708dde8719de240Steven Lang/* Nb: this file might be included in a file compiled with -ansi. So 79de890a1e48d40238dac69f302708dde8719de240Steven Lang we can't use C++ style "//" comments nor the "asm" keyword (instead 80de890a1e48d40238dac69f302708dde8719de240Steven Lang use "__asm__"). */ 81de890a1e48d40238dac69f302708dde8719de240Steven Lang 82de890a1e48d40238dac69f302708dde8719de240Steven Lang/* Derive some tags indicating what the target platform is. Note 83de890a1e48d40238dac69f302708dde8719de240Steven Lang that in this file we're using the compiler's CPP symbols for 84f5cc3d0ea8acf13c8e722da6c2d485889968d132Bruce Cran identifying architectures, which are different to the ones we use 85de890a1e48d40238dac69f302708dde8719de240Steven Lang within the rest of Valgrind. Note, __powerpc__ is active for both 86de890a1e48d40238dac69f302708dde8719de240Steven Lang 32 and 64-bit PPC, whereas __powerpc64__ is only active for the 87de890a1e48d40238dac69f302708dde8719de240Steven Lang latter (on Linux, that is). */ 88de890a1e48d40238dac69f302708dde8719de240Steven Lang#undef PLAT_x86_linux 89de890a1e48d40238dac69f302708dde8719de240Steven Lang#undef PLAT_amd64_linux 90de890a1e48d40238dac69f302708dde8719de240Steven Lang#undef PLAT_ppc32_linux 91de890a1e48d40238dac69f302708dde8719de240Steven Lang#undef PLAT_ppc64_linux 92de890a1e48d40238dac69f302708dde8719de240Steven Lang#undef PLAT_ppc32_aix5 93de890a1e48d40238dac69f302708dde8719de240Steven Lang#undef PLAT_ppc64_aix5 94de890a1e48d40238dac69f302708dde8719de240Steven Lang 95de890a1e48d40238dac69f302708dde8719de240Steven Lang#if !defined(_AIX) && defined(__i386__) 96de890a1e48d40238dac69f302708dde8719de240Steven Lang# define PLAT_x86_linux 1 97de890a1e48d40238dac69f302708dde8719de240Steven Lang#elif !defined(_AIX) && defined(__x86_64__) 98de890a1e48d40238dac69f302708dde8719de240Steven Lang# define PLAT_amd64_linux 1 996f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe#elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__) 1006f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe# define PLAT_ppc32_linux 1 1016f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe#elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__) 1026f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe# define PLAT_ppc64_linux 1 1036f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe#elif defined(_AIX) && defined(__64BIT__) 1046f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe# define PLAT_ppc64_aix5 1 105de890a1e48d40238dac69f302708dde8719de240Steven Lang#elif defined(_AIX) && !defined(__64BIT__) 106de890a1e48d40238dac69f302708dde8719de240Steven Lang# define PLAT_ppc32_aix5 1 107de890a1e48d40238dac69f302708dde8719de240Steven Lang#endif 108de890a1e48d40238dac69f302708dde8719de240Steven Lang 109371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe 110371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe/* If we're not compiling for our target platform, don't generate 111371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe any inline asms. */ 112371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe#if !defined(PLAT_x86_linux) && !defined(PLAT_amd64_linux) \ 113371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe && !defined(PLAT_ppc32_linux) && !defined(PLAT_ppc64_linux) \ 114371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe && !defined(PLAT_ppc32_aix5) && !defined(PLAT_ppc64_aix5) 115371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe# if !defined(NVALGRIND) 116371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe# define NVALGRIND 1 117371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe# endif 118371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe#endif 119371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe 120371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe 121371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe/* ------------------------------------------------------------------ */ 122371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */ 123371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe/* in here of use to end-users -- skip to the next section. */ 124d5b388a560783a61af7b424757bc6dead2309c28Jens Axboe/* ------------------------------------------------------------------ */ 125371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe 126371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe#if defined(NVALGRIND) 127371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe 128371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe/* Define NVALGRIND to completely remove the Valgrind magic sequence 129371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe from the compiled code (analogous to NDEBUG's effects on 130371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe assert()) */ 131371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe#define VALGRIND_DO_CLIENT_REQUEST( \ 132371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe _zzq_rlval, _zzq_default, _zzq_request, \ 133371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 134371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe { \ 135371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe (_zzq_rlval) = (_zzq_default); \ 136371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe } 137371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe 138371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe#else /* ! NVALGRIND */ 139371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe 140ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe/* The following defines the magic code sequences which the JITter 141ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe spots and handles magically. Don't look too closely at them as 142de890a1e48d40238dac69f302708dde8719de240Steven Lang they will rot your brain. 143ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe 1447a6499dada619928267d26b4629b0c8623dc423aJens Axboe The assembly code sequences for all architectures is in this one 1457a6499dada619928267d26b4629b0c8623dc423aJens Axboe file. This is because this file must be stand-alone, and we don't 1467a6499dada619928267d26b4629b0c8623dc423aJens Axboe want to have multiple files. 147de890a1e48d40238dac69f302708dde8719de240Steven Lang 148de890a1e48d40238dac69f302708dde8719de240Steven Lang For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default 149de890a1e48d40238dac69f302708dde8719de240Steven Lang value gets put in the return slot, so that everything works when 150de890a1e48d40238dac69f302708dde8719de240Steven Lang this is executed not under Valgrind. Args are passed in a memory 151de890a1e48d40238dac69f302708dde8719de240Steven Lang block, and so there's no intrinsic limit to the number that could 152e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe be passed, but it's currently five. 1537a6499dada619928267d26b4629b0c8623dc423aJens Axboe 154ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe The macro args are: 1553f457bea08a6bd60d99950c59c5432b8e78c69e2Bruce Cran _zzq_rlval result lvalue 156f85ac25a7d5c9d5ba4d5c73363a6a2a461a9b013Jens Axboe _zzq_default default value (result returned when running on real CPU) 157ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe _zzq_request request code 158ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe _zzq_arg1..5 request params 1595921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe 160cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe The other two macros are used to support function wrapping, and are 161ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the 1629cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe guest's NRADDR pseudo-register and whatever other information is 1637a6499dada619928267d26b4629b0c8623dc423aJens Axboe needed to safely run the call original from the wrapper: on 1649cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe ppc64-linux, the R2 value at the divert point is also needed. This 165cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe information is abstracted into a user-visible type, OrigFn. 1669cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe 1679cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe VALGRIND_CALL_NOREDIR_* behaves the same as the following on the 1689cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe guest, but guarantees that the branch instruction will not be 1699cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64: 1709cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a 1719cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe complete inline asm, since it needs to be combined with more magic 1729cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe inline asm stuff to be useful. 1739cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe*/ 1749cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe 1759cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe/* ------------------------- x86-linux ------------------------- */ 176f657a2fbbb0deaf455edc478d73b664929bcb766Jens Axboe 1779cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe#if defined(PLAT_x86_linux) 1789cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe 1799cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboetypedef 1809cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe struct { 1819cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe unsigned int nraddr; /* where's the code? */ 1829cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe } 183cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe OrigFn; 1849cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe 185cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe#define __SPECIAL_INSTRUCTION_PREAMBLE \ 1869cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe "roll $3, %%edi ; roll $13, %%edi\n\t" \ 1879cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe "roll $29, %%edi ; roll $19, %%edi\n\t" 1889cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe 189cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe#define VALGRIND_DO_CLIENT_REQUEST( \ 1909cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _zzq_rlval, _zzq_default, _zzq_request, \ 1919cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 1929cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe { volatile unsigned int _zzq_args[6]; \ 193cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe volatile unsigned int _zzq_result; \ 1949cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _zzq_args[0] = (unsigned int)(_zzq_request); \ 195cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe _zzq_args[1] = (unsigned int)(_zzq_arg1); \ 196cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe _zzq_args[2] = (unsigned int)(_zzq_arg2); \ 1979cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _zzq_args[3] = (unsigned int)(_zzq_arg3); \ 1989cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _zzq_args[4] = (unsigned int)(_zzq_arg4); \ 199cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe _zzq_args[5] = (unsigned int)(_zzq_arg5); \ 200cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 201cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe /* %EDX = client_request ( %EAX ) */ \ 202cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe "xchgl %%ebx,%%ebx" \ 203cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe : "=d" (_zzq_result) \ 204cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe : "a" (&_zzq_args[0]), "0" (_zzq_default) \ 2059cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe : "cc", "memory" \ 2069cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe ); \ 2079cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _zzq_rlval = _zzq_result; \ 2089cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe } 2099cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe 2109cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 2119cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 212cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe volatile unsigned int __addr; \ 2139cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 2149cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe /* %EAX = guest_NRADDR */ \ 2159cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe "xchgl %%ecx,%%ecx" \ 2169cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe : "=a" (__addr) \ 2179cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe : \ 2189cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe : "cc", "memory" \ 2199cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe ); \ 2209cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _zzq_orig->nraddr = __addr; \ 2219cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe } 222cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe 223f657a2fbbb0deaf455edc478d73b664929bcb766Jens Axboe#define VALGRIND_CALL_NOREDIR_EAX \ 2249cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe __SPECIAL_INSTRUCTION_PREAMBLE \ 2259cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe /* call-noredir *%EAX */ \ 2269cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe "xchgl %%edx,%%edx\n\t" 227cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe#endif /* PLAT_x86_linux */ 2289cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe 2299cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe/* ------------------------ amd64-linux ------------------------ */ 2309cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe 231cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe#if defined(PLAT_amd64_linux) 2329cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe 233cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboetypedef 234cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe struct { 2359cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe unsigned long long int nraddr; /* where's the code? */ 2369cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe } 2379cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe OrigFn; 238cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe 239cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe#define __SPECIAL_INSTRUCTION_PREAMBLE \ 2409cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \ 241cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" 242cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe 243cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe#define VALGRIND_DO_CLIENT_REQUEST( \ 244cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe _zzq_rlval, _zzq_default, _zzq_request, \ 245cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 246cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe { volatile unsigned long long int _zzq_args[6]; \ 247ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe volatile unsigned long long int _zzq_result; \ 248cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe _zzq_args[0] = (unsigned long long int)(_zzq_request); \ 2499cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ 2509cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ 251cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ 252cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ 253cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ 254cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 2559cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe /* %RDX = client_request ( %RAX ) */ \ 2569cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe "xchgq %%rbx,%%rbx" \ 2579cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe : "=d" (_zzq_result) \ 2589cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe : "a" (&_zzq_args[0]), "0" (_zzq_default) \ 2599cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe : "cc", "memory" \ 260cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe ); \ 261cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe _zzq_rlval = _zzq_result; \ 2629cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe } 263cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe 2649cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 2659cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 266cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe volatile unsigned long long int __addr; \ 267cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 268cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe /* %RAX = guest_NRADDR */ \ 269cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe "xchgq %%rcx,%%rcx" \ 2709cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe : "=a" (__addr) \ 2719cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe : \ 2729cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe : "cc", "memory" \ 2739cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe ); \ 2749cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _zzq_orig->nraddr = __addr; \ 275cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe } 276cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe 2779cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe#define VALGRIND_CALL_NOREDIR_RAX \ 278cd963e18de21e08ebb2ed86366f07347b4c58e3dJens Axboe __SPECIAL_INSTRUCTION_PREAMBLE \ 2799cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe /* call-noredir *%RAX */ \ 2805921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe "xchgq %%rdx,%%rdx\n\t" 2815921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#endif /* PLAT_amd64_linux */ 2825921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe 283af8771b9b91eb2cd23a40aaa729bad4f78acb928Jens Axboe/* ------------------------ ppc32-linux ------------------------ */ 2845921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe 2855921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#if defined(PLAT_ppc32_linux) 2865921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe 2875921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboetypedef 2885921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe struct { 289af8771b9b91eb2cd23a40aaa729bad4f78acb928Jens Axboe unsigned int nraddr; /* where's the code? */ 2905921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe } 2915921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe OrigFn; 2925921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe 2939cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe#define __SPECIAL_INSTRUCTION_PREAMBLE \ 2949cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ 2959cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" 296414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe 297de890a1e48d40238dac69f302708dde8719de240Steven Lang#define VALGRIND_DO_CLIENT_REQUEST( \ 2986f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe _zzq_rlval, _zzq_default, _zzq_request, \ 299371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 300664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe \ 301de890a1e48d40238dac69f302708dde8719de240Steven Lang { unsigned int _zzq_args[6]; \ 30262b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe unsigned int _zzq_result; \ 30362b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe unsigned int* _zzq_ptr; \ 304664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe _zzq_args[0] = (unsigned int)(_zzq_request); \ 30562b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe _zzq_args[1] = (unsigned int)(_zzq_arg1); \ 30662b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe _zzq_args[2] = (unsigned int)(_zzq_arg2); \ 307664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe _zzq_args[3] = (unsigned int)(_zzq_arg3); \ 308664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe _zzq_args[4] = (unsigned int)(_zzq_arg4); \ 309664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe _zzq_args[5] = (unsigned int)(_zzq_arg5); \ 310664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe _zzq_ptr = _zzq_args; \ 3115921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe __asm__ volatile("mr 3,%1\n\t" /*default*/ \ 3126f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe "mr 4,%2\n\t" /*ptr*/ \ 3136f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe __SPECIAL_INSTRUCTION_PREAMBLE \ 314664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe /* %R3 = client_request ( %R4 ) */ \ 3155921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe "or 1,1,1\n\t" \ 316664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe "mr %0,3" /*result*/ \ 317664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe : "=b" (_zzq_result) \ 318664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe : "b" (_zzq_default), "b" (_zzq_ptr) \ 319664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe : "cc", "memory", "r3", "r4"); \ 320664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe _zzq_rlval = _zzq_result; \ 3219cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe } 322664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe 323664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 324664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 325664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe unsigned int __addr; \ 326664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 327664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe /* %R3 = guest_NRADDR */ \ 328664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe "or 2,2,2\n\t" \ 329664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe "mr %0,3" \ 330664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe : "=b" (__addr) \ 331664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe : \ 332664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe : "cc", "memory", "r3" \ 333664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe ); \ 334664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe _zzq_orig->nraddr = __addr; \ 335664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe } 336664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe 337664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 338b96d243044023b28731341d290943b5d47a5f794Jens Axboe __SPECIAL_INSTRUCTION_PREAMBLE \ 339664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe /* branch-and-link-to-noredir *%R11 */ \ 340664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe "or 3,3,3\n\t" 341664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe#endif /* PLAT_ppc32_linux */ 342664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe 343664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe/* ------------------------ ppc64-linux ------------------------ */ 3449cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe 3459cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe#if defined(PLAT_ppc64_linux) 346414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe 3479cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboetypedef 348414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe struct { 349de890a1e48d40238dac69f302708dde8719de240Steven Lang unsigned long long int nraddr; /* where's the code? */ 3506f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe unsigned long long int r2; /* what tocptr do we need? */ 351664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe } 352664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe OrigFn; 353de890a1e48d40238dac69f302708dde8719de240Steven Lang 3545ba13ea6968cf2773f10d34376afe28ef81aeee5Jens Axboe#define __SPECIAL_INSTRUCTION_PREAMBLE \ 35562b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ 356664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe "rotldi 0,0,61 ; rotldi 0,0,51\n\t" 357664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe 35862b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe#define VALGRIND_DO_CLIENT_REQUEST( \ 359664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe _zzq_rlval, _zzq_default, _zzq_request, \ 360664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 361664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe \ 362664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe { unsigned long long int _zzq_args[6]; \ 363664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe register unsigned long long int _zzq_result __asm__("r3"); \ 364664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe register unsigned long long int* _zzq_ptr __asm__("r4"); \ 365664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe _zzq_args[0] = (unsigned long long int)(_zzq_request); \ 366664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ 367664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ 368664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ 3697d988f68c7f0ff6bd4c9e558c4defbd9a544b167Jens Axboe _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ 3707d988f68c7f0ff6bd4c9e558c4defbd9a544b167Jens Axboe _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ 3719cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _zzq_ptr = _zzq_args; \ 372664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 373664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe /* %R3 = client_request ( %R4 ) */ \ 374664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe "or 1,1,1" \ 375664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe : "=r" (_zzq_result) \ 376664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe : "0" (_zzq_default), "r" (_zzq_ptr) \ 377414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe : "cc", "memory"); \ 378664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe _zzq_rlval = _zzq_result; \ 3799cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe } 3809cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe 3816f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 3826f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 3839cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe register unsigned long long int __addr __asm__("r3"); \ 3849cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 385de890a1e48d40238dac69f302708dde8719de240Steven Lang /* %R3 = guest_NRADDR */ \ 3869cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe "or 2,2,2" \ 3879cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe : "=r" (__addr) \ 3886f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe : \ 389de890a1e48d40238dac69f302708dde8719de240Steven Lang : "cc", "memory" \ 390de890a1e48d40238dac69f302708dde8719de240Steven Lang ); \ 3919cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _zzq_orig->nraddr = __addr; \ 392414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 393414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe /* %R3 = guest_NRADDR_GPR2 */ \ 3946f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe "or 4,4,4" \ 395de890a1e48d40238dac69f302708dde8719de240Steven Lang : "=r" (__addr) \ 396de890a1e48d40238dac69f302708dde8719de240Steven Lang : \ 397414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe : "cc", "memory" \ 3989cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe ); \ 399414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe _zzq_orig->r2 = __addr; \ 400d4f12dd05cfb2e8e7a72604cd870e10f2394914eJens Axboe } 4017a6499dada619928267d26b4629b0c8623dc423aJens Axboe 402ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 403cec6b55da1c282b5b91ad346c7804171fccf151eJens Axboe __SPECIAL_INSTRUCTION_PREAMBLE \ 40422819ec237297fc39435ed566bee01a4225bfb39Jens Axboe /* branch-and-link-to-noredir *%R11 */ \ 405cec6b55da1c282b5b91ad346c7804171fccf151eJens Axboe "or 3,3,3\n\t" 406cec6b55da1c282b5b91ad346c7804171fccf151eJens Axboe 40736167d82e5f49dee91c6d2cd426068edee90e36fJens Axboe#endif /* PLAT_ppc64_linux */ 408414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe 409414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe/* ------------------------ ppc32-aix5 ------------------------- */ 410414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe 4116f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe#if defined(PLAT_ppc32_aix5) 412414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe 413414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboetypedef 414414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe struct { 415414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe unsigned int nraddr; /* where's the code? */ 416ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe unsigned int r2; /* what tocptr do we need? */ 417ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe } 41836167d82e5f49dee91c6d2cd426068edee90e36fJens Axboe OrigFn; 419e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe 420ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#define __SPECIAL_INSTRUCTION_PREAMBLE \ 42136167d82e5f49dee91c6d2cd426068edee90e36fJens Axboe "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ 422ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" 423ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe 4246f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe#define VALGRIND_DO_CLIENT_REQUEST( \ 4256f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe _zzq_rlval, _zzq_default, _zzq_request, \ 4266f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 4276f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe \ 4286f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe { unsigned int _zzq_args[7]; \ 4296f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe register unsigned int _zzq_result; \ 4306f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe register unsigned int* _zzq_ptr; \ 4316f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe _zzq_args[0] = (unsigned int)(_zzq_request); \ 4326f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe _zzq_args[1] = (unsigned int)(_zzq_arg1); \ 4336f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe _zzq_args[2] = (unsigned int)(_zzq_arg2); \ 4346f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe _zzq_args[3] = (unsigned int)(_zzq_arg3); \ 4356f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe _zzq_args[4] = (unsigned int)(_zzq_arg4); \ 4366f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe _zzq_args[5] = (unsigned int)(_zzq_arg5); \ 4376f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe _zzq_args[6] = (unsigned int)(_zzq_default); \ 4386f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe _zzq_ptr = _zzq_args; \ 4396f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe __asm__ volatile("mr 4,%1\n\t" \ 4406f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe "lwz 3, 24(4)\n\t" \ 4416f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe __SPECIAL_INSTRUCTION_PREAMBLE \ 4426f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe /* %R3 = client_request ( %R4 ) */ \ 4436f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe "or 1,1,1\n\t" \ 4446f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe "mr %0,3" \ 4456f73a7f8e2498f96aeb3df6cefba2496e17aad77Jens Axboe : "=b" (_zzq_result) \ 446b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe : "b" (_zzq_ptr) \ 447ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe : "r3", "r4", "cc", "memory"); \ 448b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe _zzq_rlval = _zzq_result; \ 449de890a1e48d40238dac69f302708dde8719de240Steven Lang } 4500fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe 451414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 452de890a1e48d40238dac69f302708dde8719de240Steven Lang { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 4530fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe register unsigned int __addr; \ 454414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 455de890a1e48d40238dac69f302708dde8719de240Steven Lang /* %R3 = guest_NRADDR */ \ 4560fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "or 2,2,2\n\t" \ 457414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe "mr %0,3" \ 458de890a1e48d40238dac69f302708dde8719de240Steven Lang : "=b" (__addr) \ 4590fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe : \ 4600fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe : "r3", "cc", "memory" \ 4610fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe ); \ 462de890a1e48d40238dac69f302708dde8719de240Steven Lang _zzq_orig->nraddr = __addr; \ 4630fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 4640fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe /* %R3 = guest_NRADDR_GPR2 */ \ 4650fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "or 4,4,4\n\t" \ 466ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe "mr %0,3" \ 4670fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe : "=b" (__addr) \ 468b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe : \ 469b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe : "r3", "cc", "memory" \ 470b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe ); \ 471ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe _zzq_orig->r2 = __addr; \ 472ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe } 473de890a1e48d40238dac69f302708dde8719de240Steven Lang 474414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 475de890a1e48d40238dac69f302708dde8719de240Steven Lang __SPECIAL_INSTRUCTION_PREAMBLE \ 4760fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe /* branch-and-link-to-noredir *%R11 */ \ 477414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe "or 3,3,3\n\t" 4780fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe 4790fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe#endif /* PLAT_ppc32_aix5 */ 480b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe 4810fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe/* ------------------------ ppc64-aix5 ------------------------- */ 4820fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe 4830fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe#if defined(PLAT_ppc64_aix5) 4840fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe 4850fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboetypedef 4860fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe struct { 4870fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe unsigned long long int nraddr; /* where's the code? */ 4880fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe unsigned long long int r2; /* what tocptr do we need? */ 4890fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe } 4900fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe OrigFn; 491b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe 4920fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe#define __SPECIAL_INSTRUCTION_PREAMBLE \ 4930fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ 494ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe "rotldi 0,0,61 ; rotldi 0,0,51\n\t" 495ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe 496ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#define VALGRIND_DO_CLIENT_REQUEST( \ 497ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe _zzq_rlval, _zzq_default, _zzq_request, \ 498ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 499b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe \ 5005fdd124a3b811993542825847f207587d5f4661eJens Axboe { unsigned long long int _zzq_args[7]; \ 501b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe register unsigned long long int _zzq_result; \ 502de890a1e48d40238dac69f302708dde8719de240Steven Lang register unsigned long long int* _zzq_ptr; \ 5035ba13ea6968cf2773f10d34376afe28ef81aeee5Jens Axboe _zzq_args[0] = (unsigned int long long)(_zzq_request); \ 504859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \ 5055fdd124a3b811993542825847f207587d5f4661eJens Axboe _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \ 506de890a1e48d40238dac69f302708dde8719de240Steven Lang _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \ 507414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \ 508414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \ 509414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe _zzq_args[6] = (unsigned int long long)(_zzq_default); \ 510414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe _zzq_ptr = _zzq_args; \ 511859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe __asm__ volatile("mr 4,%1\n\t" \ 512859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe "ld 3, 48(4)\n\t" \ 513859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe __SPECIAL_INSTRUCTION_PREAMBLE \ 5146d86144dd10b05e8b82e9b895c35dd778e5e71abJens Axboe /* %R3 = client_request ( %R4 ) */ \ 5155fdd124a3b811993542825847f207587d5f4661eJens Axboe "or 1,1,1\n\t" \ 516371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe "mr %0,3" \ 517859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe : "=b" (_zzq_result) \ 5180c09442b26216aed16f758712f744a2c54726cdbJens Axboe : "b" (_zzq_ptr) \ 519371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe : "r3", "r4", "cc", "memory"); \ 520371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe _zzq_rlval = _zzq_result; \ 521371d456c48b73c8a424e4c807c511fc891a38e7dJens Axboe } 522859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe 523b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 5245fdd124a3b811993542825847f207587d5f4661eJens Axboe { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 5250cae16ffe3e4ca17cdb88fe64d357b7cde643f6aJens Axboe register unsigned long long int __addr; \ 526859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 527b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe /* %R3 = guest_NRADDR */ \ 528859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe "or 2,2,2\n\t" \ 529859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe "mr %0,3" \ 530859088d3939ce6eccfc59a0d5559922e29e58a47Jens Axboe : "=b" (__addr) \ 531b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe : \ 532b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe : "r3", "cc", "memory" \ 533664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe ); \ 534664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe _zzq_orig->nraddr = __addr; \ 535664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 536664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe /* %R3 = guest_NRADDR_GPR2 */ \ 53762b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe "or 4,4,4\n\t" \ 538664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe "mr %0,3" \ 539664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe : "=b" (__addr) \ 540b96d243044023b28731341d290943b5d47a5f794Jens Axboe : \ 541664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe : "r3", "cc", "memory" \ 542664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe ); \ 54362b38926a8f02a03534813fc80e73e5e169bf03eJens Axboe _zzq_orig->r2 = __addr; \ 544664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe } 545664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe 546664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 547664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe __SPECIAL_INSTRUCTION_PREAMBLE \ 548664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe /* branch-and-link-to-noredir *%R11 */ \ 549664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe "or 3,3,3\n\t" 550664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe 551de890a1e48d40238dac69f302708dde8719de240Steven Lang#endif /* PLAT_ppc64_aix5 */ 552664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe 553664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe/* Insert assembly code for other platforms here... */ 554664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe 555664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe#endif /* NVALGRIND */ 556664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe 557de890a1e48d40238dac69f302708dde8719de240Steven Lang 558664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe/* ------------------------------------------------------------------ */ 559664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */ 560664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe/* ugly. It's the least-worst tradeoff I can think of. */ 561664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe/* ------------------------------------------------------------------ */ 562664fb3bde9ed3b61d0520b6b4f3d0ba9599834b0Jens Axboe 563b96d243044023b28731341d290943b5d47a5f794Jens Axboe/* This section defines magic (a.k.a appalling-hack) macros for doing 564b96d243044023b28731341d290943b5d47a5f794Jens Axboe guaranteed-no-redirection macros, so as to get from function 565b96d243044023b28731341d290943b5d47a5f794Jens Axboe wrappers to the functions they are wrapping. The whole point is to 566b96d243044023b28731341d290943b5d47a5f794Jens Axboe construct standard call sequences, but to do the call itself with a 567b96d243044023b28731341d290943b5d47a5f794Jens Axboe special no-redirect call pseudo-instruction that the JIT 568b96d243044023b28731341d290943b5d47a5f794Jens Axboe understands and handles specially. This section is long and 569b96d243044023b28731341d290943b5d47a5f794Jens Axboe repetitious, and I can't see a way to make it shorter. 570b96d243044023b28731341d290943b5d47a5f794Jens Axboe 571b96d243044023b28731341d290943b5d47a5f794Jens Axboe The naming scheme is as follows: 572b96d243044023b28731341d290943b5d47a5f794Jens Axboe 573b96d243044023b28731341d290943b5d47a5f794Jens Axboe CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc} 574b96d243044023b28731341d290943b5d47a5f794Jens Axboe 575b96d243044023b28731341d290943b5d47a5f794Jens Axboe 'W' stands for "word" and 'v' for "void". Hence there are 576b96d243044023b28731341d290943b5d47a5f794Jens Axboe different macros for calling arity 0, 1, 2, 3, 4, etc, functions, 577b96d243044023b28731341d290943b5d47a5f794Jens Axboe and for each, the possibility of returning a word-typed result, or 578b96d243044023b28731341d290943b5d47a5f794Jens Axboe no result. 579b96d243044023b28731341d290943b5d47a5f794Jens Axboe*/ 580b96d243044023b28731341d290943b5d47a5f794Jens Axboe 581b96d243044023b28731341d290943b5d47a5f794Jens Axboe/* Use these to write the name of your wrapper. NOTE: duplicates 582b96d243044023b28731341d290943b5d47a5f794Jens Axboe VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */ 583b96d243044023b28731341d290943b5d47a5f794Jens Axboe 584b96d243044023b28731341d290943b5d47a5f794Jens Axboe#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \ 585b96d243044023b28731341d290943b5d47a5f794Jens Axboe _vgwZU_##soname##_##fnname 586b96d243044023b28731341d290943b5d47a5f794Jens Axboe 587b96d243044023b28731341d290943b5d47a5f794Jens Axboe#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \ 588b96d243044023b28731341d290943b5d47a5f794Jens Axboe _vgwZZ_##soname##_##fnname 589b96d243044023b28731341d290943b5d47a5f794Jens Axboe 590b96d243044023b28731341d290943b5d47a5f794Jens Axboe/* Use this macro from within a wrapper function to collect the 591b96d243044023b28731341d290943b5d47a5f794Jens Axboe context (address and possibly other info) of the original function. 592b96d243044023b28731341d290943b5d47a5f794Jens Axboe Once you have that you can then use it in one of the CALL_FN_ 593b96d243044023b28731341d290943b5d47a5f794Jens Axboe macros. The type of the argument _lval is OrigFn. */ 594b96d243044023b28731341d290943b5d47a5f794Jens Axboe#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval) 595b96d243044023b28731341d290943b5d47a5f794Jens Axboe 596b96d243044023b28731341d290943b5d47a5f794Jens Axboe/* Derivatives of the main macros below, for calling functions 597b96d243044023b28731341d290943b5d47a5f794Jens Axboe returning void. */ 598b96d243044023b28731341d290943b5d47a5f794Jens Axboe 599b96d243044023b28731341d290943b5d47a5f794Jens Axboe#define CALL_FN_v_v(fnptr) \ 600b96d243044023b28731341d290943b5d47a5f794Jens Axboe do { volatile unsigned long _junk; \ 601b96d243044023b28731341d290943b5d47a5f794Jens Axboe CALL_FN_W_v(_junk,fnptr); } while (0) 602b96d243044023b28731341d290943b5d47a5f794Jens Axboe 603b96d243044023b28731341d290943b5d47a5f794Jens Axboe#define CALL_FN_v_W(fnptr, arg1) \ 604b96d243044023b28731341d290943b5d47a5f794Jens Axboe do { volatile unsigned long _junk; \ 605b96d243044023b28731341d290943b5d47a5f794Jens Axboe CALL_FN_W_W(_junk,fnptr,arg1); } while (0) 606b96d243044023b28731341d290943b5d47a5f794Jens Axboe 607b96d243044023b28731341d290943b5d47a5f794Jens Axboe#define CALL_FN_v_WW(fnptr, arg1,arg2) \ 608b96d243044023b28731341d290943b5d47a5f794Jens Axboe do { volatile unsigned long _junk; \ 609b96d243044023b28731341d290943b5d47a5f794Jens Axboe CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0) 610b96d243044023b28731341d290943b5d47a5f794Jens Axboe 611b96d243044023b28731341d290943b5d47a5f794Jens Axboe#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \ 612b96d243044023b28731341d290943b5d47a5f794Jens Axboe do { volatile unsigned long _junk; \ 613b96d243044023b28731341d290943b5d47a5f794Jens Axboe CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0) 614b96d243044023b28731341d290943b5d47a5f794Jens Axboe 615b96d243044023b28731341d290943b5d47a5f794Jens Axboe/* ------------------------- x86-linux ------------------------- */ 616b96d243044023b28731341d290943b5d47a5f794Jens Axboe 617b96d243044023b28731341d290943b5d47a5f794Jens Axboe#if defined(PLAT_x86_linux) 618b96d243044023b28731341d290943b5d47a5f794Jens Axboe 619b96d243044023b28731341d290943b5d47a5f794Jens Axboe/* These regs are trashed by the hidden call. No need to mention eax 620b96d243044023b28731341d290943b5d47a5f794Jens Axboe as gcc can already see that, plus causes gcc to bomb. */ 621b96d243044023b28731341d290943b5d47a5f794Jens Axboe#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx" 622b96d243044023b28731341d290943b5d47a5f794Jens Axboe 623b96d243044023b28731341d290943b5d47a5f794Jens Axboe/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned 624b96d243044023b28731341d290943b5d47a5f794Jens Axboe long) == 4. */ 625b96d243044023b28731341d290943b5d47a5f794Jens Axboe 626b96d243044023b28731341d290943b5d47a5f794Jens Axboe#define CALL_FN_W_v(lval, orig) \ 627b96d243044023b28731341d290943b5d47a5f794Jens Axboe do { \ 628b96d243044023b28731341d290943b5d47a5f794Jens Axboe volatile OrigFn _orig = (orig); \ 629b96d243044023b28731341d290943b5d47a5f794Jens Axboe volatile unsigned long _argvec[1]; \ 630b96d243044023b28731341d290943b5d47a5f794Jens Axboe volatile unsigned long _res; \ 631b96d243044023b28731341d290943b5d47a5f794Jens Axboe _argvec[0] = (unsigned long)_orig.nraddr; \ 632b96d243044023b28731341d290943b5d47a5f794Jens Axboe __asm__ volatile( \ 633b96d243044023b28731341d290943b5d47a5f794Jens Axboe "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 634b96d243044023b28731341d290943b5d47a5f794Jens Axboe VALGRIND_CALL_NOREDIR_EAX \ 635b96d243044023b28731341d290943b5d47a5f794Jens Axboe : /*out*/ "=a" (_res) \ 636b96d243044023b28731341d290943b5d47a5f794Jens Axboe : /*in*/ "a" (&_argvec[0]) \ 637b96d243044023b28731341d290943b5d47a5f794Jens Axboe : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 638b96d243044023b28731341d290943b5d47a5f794Jens Axboe ); \ 639b96d243044023b28731341d290943b5d47a5f794Jens Axboe lval = (__typeof__(lval)) _res; \ 640b96d243044023b28731341d290943b5d47a5f794Jens Axboe } while (0) 6410fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe 6420fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe#define CALL_FN_W_W(lval, orig, arg1) \ 643b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe do { \ 644b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe volatile OrigFn _orig = (orig); \ 645b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe volatile unsigned long _argvec[2]; \ 646166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe volatile unsigned long _res; \ 647166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe _argvec[0] = (unsigned long)_orig.nraddr; \ 648166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe _argvec[1] = (unsigned long)(arg1); \ 649166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe __asm__ volatile( \ 650166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe "pushl 4(%%eax)\n\t" \ 651166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 652166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe VALGRIND_CALL_NOREDIR_EAX \ 653166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe "addl $4, %%esp\n" \ 654166dce4bdf2573a1641c1de5243e2465b190f0ddJens Axboe : /*out*/ "=a" (_res) \ 655b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe : /*in*/ "a" (&_argvec[0]) \ 656b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 657b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe ); \ 658b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe lval = (__typeof__(lval)) _res; \ 659b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe } while (0) 660b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe 661b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 662b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe do { \ 663b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe volatile OrigFn _orig = (orig); \ 664b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe volatile unsigned long _argvec[3]; \ 6655fdd124a3b811993542825847f207587d5f4661eJens Axboe volatile unsigned long _res; \ 666b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe _argvec[0] = (unsigned long)_orig.nraddr; \ 667b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe _argvec[1] = (unsigned long)(arg1); \ 6685fdd124a3b811993542825847f207587d5f4661eJens Axboe _argvec[2] = (unsigned long)(arg2); \ 6695fdd124a3b811993542825847f207587d5f4661eJens Axboe __asm__ volatile( \ 6705fdd124a3b811993542825847f207587d5f4661eJens Axboe "pushl 8(%%eax)\n\t" \ 6715fdd124a3b811993542825847f207587d5f4661eJens Axboe "pushl 4(%%eax)\n\t" \ 6725fdd124a3b811993542825847f207587d5f4661eJens Axboe "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 6730fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe VALGRIND_CALL_NOREDIR_EAX \ 6740fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "addl $8, %%esp\n" \ 6750fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe : /*out*/ "=a" (_res) \ 6760fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe : /*in*/ "a" (&_argvec[0]) \ 6770fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 6780fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe ); \ 6790fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe lval = (__typeof__(lval)) _res; \ 6800fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe } while (0) 6810fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe 6820fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 6830fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe do { \ 684de890a1e48d40238dac69f302708dde8719de240Steven Lang volatile OrigFn _orig = (orig); \ 6850fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe volatile unsigned long _argvec[4]; \ 686de890a1e48d40238dac69f302708dde8719de240Steven Lang volatile unsigned long _res; \ 6870fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe _argvec[0] = (unsigned long)_orig.nraddr; \ 688de890a1e48d40238dac69f302708dde8719de240Steven Lang _argvec[1] = (unsigned long)(arg1); \ 689de890a1e48d40238dac69f302708dde8719de240Steven Lang _argvec[2] = (unsigned long)(arg2); \ 6900fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe _argvec[3] = (unsigned long)(arg3); \ 691de890a1e48d40238dac69f302708dde8719de240Steven Lang __asm__ volatile( \ 6920fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "pushl 12(%%eax)\n\t" \ 6930fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "pushl 8(%%eax)\n\t" \ 6940fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "pushl 4(%%eax)\n\t" \ 6950fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 6960fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe VALGRIND_CALL_NOREDIR_EAX \ 6970fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "addl $12, %%esp\n" \ 6980fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe : /*out*/ "=a" (_res) \ 6990fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe : /*in*/ "a" (&_argvec[0]) \ 7000fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 7010fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe ); \ 7020fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe lval = (__typeof__(lval)) _res; \ 7030fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe } while (0) 7040fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe 7050fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 7060fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe do { \ 7070fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe volatile OrigFn _orig = (orig); \ 7080fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe volatile unsigned long _argvec[5]; \ 7090fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe volatile unsigned long _res; \ 7100fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe _argvec[0] = (unsigned long)_orig.nraddr; \ 7110fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe _argvec[1] = (unsigned long)(arg1); \ 7120fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe _argvec[2] = (unsigned long)(arg2); \ 7130fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe _argvec[3] = (unsigned long)(arg3); \ 7140fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe _argvec[4] = (unsigned long)(arg4); \ 7150fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe __asm__ volatile( \ 7160fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "pushl 16(%%eax)\n\t" \ 7170fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "pushl 12(%%eax)\n\t" \ 718b94cba47cfdf96e72ec894080b3a7bf645a86e9cJens Axboe "pushl 8(%%eax)\n\t" \ 7190fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "pushl 4(%%eax)\n\t" \ 7200fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 7210fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe VALGRIND_CALL_NOREDIR_EAX \ 7220fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "addl $16, %%esp\n" \ 7230fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe : /*out*/ "=a" (_res) \ 7240fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe : /*in*/ "a" (&_argvec[0]) \ 7250fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 7260fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe ); \ 7270fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe lval = (__typeof__(lval)) _res; \ 728ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe } while (0) 729b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe 730de890a1e48d40238dac69f302708dde8719de240Steven Lang#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 731414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe do { \ 732ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe volatile OrigFn _orig = (orig); \ 733de890a1e48d40238dac69f302708dde8719de240Steven Lang volatile unsigned long _argvec[6]; \ 734414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe volatile unsigned long _res; \ 735414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe _argvec[0] = (unsigned long)_orig.nraddr; \ 736414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe _argvec[1] = (unsigned long)(arg1); \ 737414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe _argvec[2] = (unsigned long)(arg2); \ 7380fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe _argvec[3] = (unsigned long)(arg3); \ 739ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe _argvec[4] = (unsigned long)(arg4); \ 740e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe _argvec[5] = (unsigned long)(arg5); \ 741ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe __asm__ volatile( \ 742ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe "pushl 20(%%eax)\n\t" \ 743ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe "pushl 16(%%eax)\n\t" \ 744ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe "pushl 12(%%eax)\n\t" \ 745ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe "pushl 8(%%eax)\n\t" \ 746e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe "pushl 4(%%eax)\n\t" \ 747ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 748ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe VALGRIND_CALL_NOREDIR_EAX \ 7496bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe "addl $20, %%esp\n" \ 7506bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe : /*out*/ "=a" (_res) \ 751e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe : /*in*/ "a" (&_argvec[0]) \ 7526bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 7536bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe ); \ 7546bedbfafcffbc7202b5bb621ac5886aafdc0f362Jens Axboe lval = (__typeof__(lval)) _res; \ 755ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe } while (0) 756b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe 757b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 758b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe do { \ 759ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe volatile OrigFn _orig = (orig); \ 760b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe volatile unsigned long _argvec[7]; \ 761e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe volatile unsigned long _res; \ 762ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe _argvec[0] = (unsigned long)_orig.nraddr; \ 763ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe _argvec[1] = (unsigned long)(arg1); \ 7640fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe _argvec[2] = (unsigned long)(arg2); \ 7650fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe _argvec[3] = (unsigned long)(arg3); \ 7660fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe _argvec[4] = (unsigned long)(arg4); \ 7670fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe _argvec[5] = (unsigned long)(arg5); \ 7680fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe _argvec[6] = (unsigned long)(arg6); \ 769de890a1e48d40238dac69f302708dde8719de240Steven Lang __asm__ volatile( \ 7700fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "pushl 24(%%eax)\n\t" \ 7710fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "pushl 20(%%eax)\n\t" \ 772de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 16(%%eax)\n\t" \ 7730fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "pushl 12(%%eax)\n\t" \ 7740fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "pushl 8(%%eax)\n\t" \ 775de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 4(%%eax)\n\t" \ 776de890a1e48d40238dac69f302708dde8719de240Steven Lang "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 7770fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe VALGRIND_CALL_NOREDIR_EAX \ 778de890a1e48d40238dac69f302708dde8719de240Steven Lang "addl $24, %%esp\n" \ 7790fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe : /*out*/ "=a" (_res) \ 7800fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe : /*in*/ "a" (&_argvec[0]) \ 7810fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 782de890a1e48d40238dac69f302708dde8719de240Steven Lang ); \ 7830fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe lval = (__typeof__(lval)) _res; \ 7840fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe } while (0) 7850fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe 786e1161c325f7866bae879e686d1c673ca32ab09aeJens Axboe#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 7870fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe arg7) \ 788ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe do { \ 789ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe volatile OrigFn _orig = (orig); \ 790ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe volatile unsigned long _argvec[8]; \ 791b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe volatile unsigned long _res; \ 792ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe _argvec[0] = (unsigned long)_orig.nraddr; \ 793ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe _argvec[1] = (unsigned long)(arg1); \ 7949bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe _argvec[2] = (unsigned long)(arg2); \ 795ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe _argvec[3] = (unsigned long)(arg3); \ 796de890a1e48d40238dac69f302708dde8719de240Steven Lang _argvec[4] = (unsigned long)(arg4); \ 797af52b3455ad892322aab2791282b6bd4efdfdbf3Jens Axboe _argvec[5] = (unsigned long)(arg5); \ 798ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe _argvec[6] = (unsigned long)(arg6); \ 7993f457bea08a6bd60d99950c59c5432b8e78c69e2Bruce Cran _argvec[7] = (unsigned long)(arg7); \ 8003f457bea08a6bd60d99950c59c5432b8e78c69e2Bruce Cran __asm__ volatile( \ 8013f457bea08a6bd60d99950c59c5432b8e78c69e2Bruce Cran "pushl 28(%%eax)\n\t" \ 8023f457bea08a6bd60d99950c59c5432b8e78c69e2Bruce Cran "pushl 24(%%eax)\n\t" \ 8033f457bea08a6bd60d99950c59c5432b8e78c69e2Bruce Cran "pushl 20(%%eax)\n\t" \ 80416d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe "pushl 16(%%eax)\n\t" \ 80516d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe "pushl 12(%%eax)\n\t" \ 80616d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe "pushl 8(%%eax)\n\t" \ 80716d55aae770b8b1a966d4b4a814918ce49a76ba3Jens Axboe "pushl 4(%%eax)\n\t" \ 808ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 809de890a1e48d40238dac69f302708dde8719de240Steven Lang VALGRIND_CALL_NOREDIR_EAX \ 810de890a1e48d40238dac69f302708dde8719de240Steven Lang "addl $28, %%esp\n" \ 811de890a1e48d40238dac69f302708dde8719de240Steven Lang : /*out*/ "=a" (_res) \ 812de890a1e48d40238dac69f302708dde8719de240Steven Lang : /*in*/ "a" (&_argvec[0]) \ 813de890a1e48d40238dac69f302708dde8719de240Steven Lang : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 814de890a1e48d40238dac69f302708dde8719de240Steven Lang ); \ 815de890a1e48d40238dac69f302708dde8719de240Steven Lang lval = (__typeof__(lval)) _res; \ 816ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe } while (0) 817de890a1e48d40238dac69f302708dde8719de240Steven Lang 818de890a1e48d40238dac69f302708dde8719de240Steven Lang#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 8199b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe arg7,arg8) \ 8209b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe do { \ 821de890a1e48d40238dac69f302708dde8719de240Steven Lang volatile OrigFn _orig = (orig); \ 822de890a1e48d40238dac69f302708dde8719de240Steven Lang volatile unsigned long _argvec[9]; \ 8239b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe volatile unsigned long _res; \ 824de890a1e48d40238dac69f302708dde8719de240Steven Lang _argvec[0] = (unsigned long)_orig.nraddr; \ 8259b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe _argvec[1] = (unsigned long)(arg1); \ 8269b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe _argvec[2] = (unsigned long)(arg2); \ 8279b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe _argvec[3] = (unsigned long)(arg3); \ 8289b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe _argvec[4] = (unsigned long)(arg4); \ 8299b9860651274cfb6e5a367b653e0d465bd89344fJens Axboe _argvec[5] = (unsigned long)(arg5); \ 830de890a1e48d40238dac69f302708dde8719de240Steven Lang _argvec[6] = (unsigned long)(arg6); \ 831de890a1e48d40238dac69f302708dde8719de240Steven Lang _argvec[7] = (unsigned long)(arg7); \ 832de890a1e48d40238dac69f302708dde8719de240Steven Lang _argvec[8] = (unsigned long)(arg8); \ 833443662efa60d9082bc820641e7d1d31dd58d3ae1Jens Axboe __asm__ volatile( \ 834de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 32(%%eax)\n\t" \ 835de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 28(%%eax)\n\t" \ 836de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 24(%%eax)\n\t" \ 837414c2a3e741bb7dd7147ce6843f529c7773cea38Jens Axboe "pushl 20(%%eax)\n\t" \ 8380fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "pushl 16(%%eax)\n\t" \ 839de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 12(%%eax)\n\t" \ 840de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 8(%%eax)\n\t" \ 8410fd666bf0d5fc373f28b1b43d1df817f8ec89605Jens Axboe "pushl 4(%%eax)\n\t" \ 842de890a1e48d40238dac69f302708dde8719de240Steven Lang "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 843ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe VALGRIND_CALL_NOREDIR_EAX \ 8447bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe "addl $32, %%esp\n" \ 845ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe : /*out*/ "=a" (_res) \ 846ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe : /*in*/ "a" (&_argvec[0]) \ 847b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 8489bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe ); \ 849b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe lval = (__typeof__(lval)) _res; \ 850b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe } while (0) 851b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe 85264b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 85364b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe arg7,arg8,arg9) \ 85464b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe do { \ 85564b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe volatile OrigFn _orig = (orig); \ 85664b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe volatile unsigned long _argvec[10]; \ 85764b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe volatile unsigned long _res; \ 85864b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe _argvec[0] = (unsigned long)_orig.nraddr; \ 859b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe _argvec[1] = (unsigned long)(arg1); \ 860b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe _argvec[2] = (unsigned long)(arg2); \ 861b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe _argvec[3] = (unsigned long)(arg3); \ 862b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe _argvec[4] = (unsigned long)(arg4); \ 863b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe _argvec[5] = (unsigned long)(arg5); \ 864b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe _argvec[6] = (unsigned long)(arg6); \ 8657bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe _argvec[7] = (unsigned long)(arg7); \ 8667bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe _argvec[8] = (unsigned long)(arg8); \ 867de890a1e48d40238dac69f302708dde8719de240Steven Lang _argvec[9] = (unsigned long)(arg9); \ 868de890a1e48d40238dac69f302708dde8719de240Steven Lang __asm__ volatile( \ 869de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 36(%%eax)\n\t" \ 870de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 32(%%eax)\n\t" \ 871de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 28(%%eax)\n\t" \ 8727bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe "pushl 24(%%eax)\n\t" \ 8737bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe "pushl 20(%%eax)\n\t" \ 8747bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe "pushl 16(%%eax)\n\t" \ 8757bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe "pushl 12(%%eax)\n\t" \ 8767bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe "pushl 8(%%eax)\n\t" \ 87764b24cd8a5ea87bccec60e0236d93071480201e7Jens Axboe "pushl 4(%%eax)\n\t" \ 8787bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 8797bb48f84ac78cac1f90e3e04d0220d90d6a64a6bJens Axboe VALGRIND_CALL_NOREDIR_EAX \ 880b5af82930ccfd7dda6a1b11794efb452eb76d8dcJens Axboe "addl $36, %%esp\n" \ 8819bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe : /*out*/ "=a" (_res) \ 8829bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe : /*in*/ "a" (&_argvec[0]) \ 8839bec88e15aad76c16ac65048270ecac8b5956a61Jens Axboe : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 88436d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe ); \ 88536d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe lval = (__typeof__(lval)) _res; \ 88636d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe } while (0) 88736d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe 88836d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 8895921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe arg7,arg8,arg9,arg10) \ 8909cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe do { \ 8919cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe volatile OrigFn _orig = (orig); \ 8929cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe volatile unsigned long _argvec[11]; \ 8939cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe volatile unsigned long _res; \ 8949cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _argvec[0] = (unsigned long)_orig.nraddr; \ 8959cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _argvec[1] = (unsigned long)(arg1); \ 8969cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _argvec[2] = (unsigned long)(arg2); \ 8979cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _argvec[3] = (unsigned long)(arg3); \ 8989cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _argvec[4] = (unsigned long)(arg4); \ 8999cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _argvec[5] = (unsigned long)(arg5); \ 9009cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _argvec[6] = (unsigned long)(arg6); \ 9019cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _argvec[7] = (unsigned long)(arg7); \ 9029cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _argvec[8] = (unsigned long)(arg8); \ 9039cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _argvec[9] = (unsigned long)(arg9); \ 9049cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _argvec[10] = (unsigned long)(arg10); \ 9059cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe __asm__ volatile( \ 9069cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe "pushl 40(%%eax)\n\t" \ 9079cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe "pushl 36(%%eax)\n\t" \ 9085921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe "pushl 32(%%eax)\n\t" \ 909de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 28(%%eax)\n\t" \ 910de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 24(%%eax)\n\t" \ 911de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 20(%%eax)\n\t" \ 912de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 16(%%eax)\n\t" \ 913de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 12(%%eax)\n\t" \ 914de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 8(%%eax)\n\t" \ 915de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 4(%%eax)\n\t" \ 916de890a1e48d40238dac69f302708dde8719de240Steven Lang "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 91736d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe VALGRIND_CALL_NOREDIR_EAX \ 91836d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe "addl $40, %%esp\n" \ 919de890a1e48d40238dac69f302708dde8719de240Steven Lang : /*out*/ "=a" (_res) \ 920de890a1e48d40238dac69f302708dde8719de240Steven Lang : /*in*/ "a" (&_argvec[0]) \ 921de890a1e48d40238dac69f302708dde8719de240Steven Lang : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 92236d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe ); \ 923ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe lval = (__typeof__(lval)) _res; \ 9245921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe } while (0) 925ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe 9265921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ 927de890a1e48d40238dac69f302708dde8719de240Steven Lang arg6,arg7,arg8,arg9,arg10, \ 928de890a1e48d40238dac69f302708dde8719de240Steven Lang arg11) \ 929de890a1e48d40238dac69f302708dde8719de240Steven Lang do { \ 930de890a1e48d40238dac69f302708dde8719de240Steven Lang volatile OrigFn _orig = (orig); \ 931de890a1e48d40238dac69f302708dde8719de240Steven Lang volatile unsigned long _argvec[12]; \ 932de890a1e48d40238dac69f302708dde8719de240Steven Lang volatile unsigned long _res; \ 933de890a1e48d40238dac69f302708dde8719de240Steven Lang _argvec[0] = (unsigned long)_orig.nraddr; \ 934de890a1e48d40238dac69f302708dde8719de240Steven Lang _argvec[1] = (unsigned long)(arg1); \ 935de890a1e48d40238dac69f302708dde8719de240Steven Lang _argvec[2] = (unsigned long)(arg2); \ 93636d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe _argvec[3] = (unsigned long)(arg3); \ 937de890a1e48d40238dac69f302708dde8719de240Steven Lang _argvec[4] = (unsigned long)(arg4); \ 938de890a1e48d40238dac69f302708dde8719de240Steven Lang _argvec[5] = (unsigned long)(arg5); \ 939de890a1e48d40238dac69f302708dde8719de240Steven Lang _argvec[6] = (unsigned long)(arg6); \ 94036d80bc7c7f7fbc2612941b7dd7ceaf645798c7fJens Axboe _argvec[7] = (unsigned long)(arg7); \ 9419cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _argvec[8] = (unsigned long)(arg8); \ 9429cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe _argvec[9] = (unsigned long)(arg9); \ 943de890a1e48d40238dac69f302708dde8719de240Steven Lang _argvec[10] = (unsigned long)(arg10); \ 944de890a1e48d40238dac69f302708dde8719de240Steven Lang _argvec[11] = (unsigned long)(arg11); \ 945de890a1e48d40238dac69f302708dde8719de240Steven Lang __asm__ volatile( \ 946de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 44(%%eax)\n\t" \ 947de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 40(%%eax)\n\t" \ 948de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 36(%%eax)\n\t" \ 949de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 32(%%eax)\n\t" \ 950de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 28(%%eax)\n\t" \ 951de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 24(%%eax)\n\t" \ 952de890a1e48d40238dac69f302708dde8719de240Steven Lang "pushl 20(%%eax)\n\t" \ 953ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe "pushl 16(%%eax)\n\t" \ 954ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe "pushl 12(%%eax)\n\t" \ 9559cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe "pushl 8(%%eax)\n\t" \ 9565921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe "pushl 4(%%eax)\n\t" \ 9579cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 9585921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe VALGRIND_CALL_NOREDIR_EAX \ 959ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe "addl $44, %%esp\n" \ 960ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe : /*out*/ "=a" (_res) \ 961ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe : /*in*/ "a" (&_argvec[0]) \ 962ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 9639cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe ); \ 9645921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe lval = (__typeof__(lval)) _res; \ 9659cce02e89e01984a5bf58e730fb9311dc5273554Jens Axboe } while (0) 9665921e80c5dfc9f96d2f21da6ae58f2b5d3a0b373Jens Axboe 967ed92ac0ce9ce1cc64697272d307d4fa7d18ed64cJens Axboe#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