Sirikata
|
00001 /* -*- c -*- 00002 00003 This file is part of Valgrind, a dynamic binary instrumentation 00004 framework. 00005 00006 Copyright (C) 2000-2008 Julian Seward. All rights reserved. 00007 00008 Redistribution and use in source and binary forms, with or without 00009 modification, are permitted provided that the following conditions 00010 are met: 00011 00012 1. Redistributions of source code must retain the above copyright 00013 notice, this list of conditions and the following disclaimer. 00014 00015 2. The origin of this software must not be misrepresented; you must 00016 not claim that you wrote the original software. If you use this 00017 software in a product, an acknowledgment in the product 00018 documentation would be appreciated but is not required. 00019 00020 3. Altered source versions must be plainly marked as such, and must 00021 not be misrepresented as being the original software. 00022 00023 4. The name of the author may not be used to endorse or promote 00024 products derived from this software without specific prior written 00025 permission. 00026 00027 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 00028 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00029 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00030 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00031 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00032 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00033 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00034 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 00035 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00036 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00037 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00038 00039 */ 00040 00041 00042 /* This file is for inclusion into client (your!) code. 00043 00044 You can use these macros to manipulate and query Valgrind's 00045 execution inside your own programs. 00046 00047 The resulting executables will still run without Valgrind, just a 00048 little bit more slowly than they otherwise would, but otherwise 00049 unchanged. When not running on valgrind, each client request 00050 consumes very few (eg. 7) instructions, so the resulting performance 00051 loss is negligible unless you plan to execute client requests 00052 millions of times per second. Nevertheless, if that is still a 00053 problem, you can compile with the NVALGRIND symbol defined (gcc 00054 -DNVALGRIND) so that client requests are not even compiled in. */ 00055 00056 #ifndef __VALGRIND_H 00057 #define __VALGRIND_H 00058 00059 #include <stdarg.h> 00060 00061 /* Nb: this file might be included in a file compiled with -ansi. So 00062 we can't use C++ style "//" comments nor the "asm" keyword (instead 00063 use "__asm__"). */ 00064 00065 /* Derive some tags indicating what the target platform is. Note 00066 that in this file we're using the compiler's CPP symbols for 00067 identifying architectures, which are different to the ones we use 00068 within the rest of Valgrind. Note, __powerpc__ is active for both 00069 32 and 64-bit PPC, whereas __powerpc64__ is only active for the 00070 latter (on Linux, that is). */ 00071 #undef PLAT_x86_linux 00072 #undef PLAT_amd64_linux 00073 #undef PLAT_ppc32_linux 00074 #undef PLAT_ppc64_linux 00075 #undef PLAT_ppc32_aix5 00076 #undef PLAT_ppc64_aix5 00077 00078 #if !defined(_AIX) && defined(__i386__) 00079 # define PLAT_x86_linux 1 00080 #elif !defined(_AIX) && defined(__x86_64__) 00081 # define PLAT_amd64_linux 1 00082 #elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__) 00083 # define PLAT_ppc32_linux 1 00084 #elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__) 00085 # define PLAT_ppc64_linux 1 00086 #elif defined(_AIX) && defined(__64BIT__) 00087 # define PLAT_ppc64_aix5 1 00088 #elif defined(_AIX) && !defined(__64BIT__) 00089 # define PLAT_ppc32_aix5 1 00090 #endif 00091 00092 00093 /* If we're not compiling for our target platform, don't generate 00094 any inline asms. */ 00095 #if !defined(PLAT_x86_linux) && !defined(PLAT_amd64_linux) \ 00096 && !defined(PLAT_ppc32_linux) && !defined(PLAT_ppc64_linux) \ 00097 && !defined(PLAT_ppc32_aix5) && !defined(PLAT_ppc64_aix5) 00098 # if !defined(NVALGRIND) 00099 # define NVALGRIND 1 00100 # endif 00101 #endif 00102 00103 00104 /* ------------------------------------------------------------------ */ 00105 /* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */ 00106 /* in here of use to end-users -- skip to the next section. */ 00107 /* ------------------------------------------------------------------ */ 00108 00109 #if defined(NVALGRIND) 00110 00111 /* Define NVALGRIND to completely remove the Valgrind magic sequence 00112 from the compiled code (analogous to NDEBUG's effects on 00113 assert()) */ 00114 #define VALGRIND_DO_CLIENT_REQUEST( \ 00115 _zzq_rlval, _zzq_default, _zzq_request, \ 00116 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 00117 { \ 00118 (_zzq_rlval) = (_zzq_default); \ 00119 } 00120 00121 #else /* ! NVALGRIND */ 00122 00123 /* The following defines the magic code sequences which the JITter 00124 spots and handles magically. Don't look too closely at them as 00125 they will rot your brain. 00126 00127 The assembly code sequences for all architectures is in this one 00128 file. This is because this file must be stand-alone, and we don't 00129 want to have multiple files. 00130 00131 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default 00132 value gets put in the return slot, so that everything works when 00133 this is executed not under Valgrind. Args are passed in a memory 00134 block, and so there's no intrinsic limit to the number that could 00135 be passed, but it's currently five. 00136 00137 The macro args are: 00138 _zzq_rlval result lvalue 00139 _zzq_default default value (result returned when running on real CPU) 00140 _zzq_request request code 00141 _zzq_arg1..5 request params 00142 00143 The other two macros are used to support function wrapping, and are 00144 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the 00145 guest's NRADDR pseudo-register and whatever other information is 00146 needed to safely run the call original from the wrapper: on 00147 ppc64-linux, the R2 value at the divert point is also needed. This 00148 information is abstracted into a user-visible type, OrigFn. 00149 00150 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the 00151 guest, but guarantees that the branch instruction will not be 00152 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64: 00153 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a 00154 complete inline asm, since it needs to be combined with more magic 00155 inline asm stuff to be useful. 00156 */ 00157 00158 /* ------------------------- x86-linux ------------------------- */ 00159 00160 #if defined(PLAT_x86_linux) 00161 00162 typedef 00163 struct { 00164 unsigned int nraddr; /* where's the code? */ 00165 } 00166 OrigFn; 00167 00168 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 00169 "roll $3, %%edi ; roll $13, %%edi\n\t" \ 00170 "roll $29, %%edi ; roll $19, %%edi\n\t" 00171 00172 #define VALGRIND_DO_CLIENT_REQUEST( \ 00173 _zzq_rlval, _zzq_default, _zzq_request, \ 00174 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 00175 { volatile unsigned int _zzq_args[6]; \ 00176 volatile unsigned int _zzq_result; \ 00177 _zzq_args[0] = (unsigned int)(_zzq_request); \ 00178 _zzq_args[1] = (unsigned int)(_zzq_arg1); \ 00179 _zzq_args[2] = (unsigned int)(_zzq_arg2); \ 00180 _zzq_args[3] = (unsigned int)(_zzq_arg3); \ 00181 _zzq_args[4] = (unsigned int)(_zzq_arg4); \ 00182 _zzq_args[5] = (unsigned int)(_zzq_arg5); \ 00183 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 00184 /* %EDX = client_request ( %EAX ) */ \ 00185 "xchgl %%ebx,%%ebx" \ 00186 : "=d" (_zzq_result) \ 00187 : "a" (&_zzq_args[0]), "0" (_zzq_default) \ 00188 : "cc", "memory" \ 00189 ); \ 00190 _zzq_rlval = _zzq_result; \ 00191 } 00192 00193 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 00194 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 00195 volatile unsigned int __addr; \ 00196 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 00197 /* %EAX = guest_NRADDR */ \ 00198 "xchgl %%ecx,%%ecx" \ 00199 : "=a" (__addr) \ 00200 : \ 00201 : "cc", "memory" \ 00202 ); \ 00203 _zzq_orig->nraddr = __addr; \ 00204 } 00205 00206 #define VALGRIND_CALL_NOREDIR_EAX \ 00207 __SPECIAL_INSTRUCTION_PREAMBLE \ 00208 /* call-noredir *%EAX */ \ 00209 "xchgl %%edx,%%edx\n\t" 00210 #endif /* PLAT_x86_linux */ 00211 00212 /* ------------------------ amd64-linux ------------------------ */ 00213 00214 #if defined(PLAT_amd64_linux) 00215 00216 typedef 00217 struct { 00218 unsigned long long int nraddr; /* where's the code? */ 00219 } 00220 OrigFn; 00221 00222 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 00223 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \ 00224 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" 00225 00226 #define VALGRIND_DO_CLIENT_REQUEST( \ 00227 _zzq_rlval, _zzq_default, _zzq_request, \ 00228 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 00229 { volatile unsigned long long int _zzq_args[6]; \ 00230 volatile unsigned long long int _zzq_result; \ 00231 _zzq_args[0] = (unsigned long long int)(_zzq_request); \ 00232 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ 00233 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ 00234 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ 00235 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ 00236 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ 00237 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 00238 /* %RDX = client_request ( %RAX ) */ \ 00239 "xchgq %%rbx,%%rbx" \ 00240 : "=d" (_zzq_result) \ 00241 : "a" (&_zzq_args[0]), "0" (_zzq_default) \ 00242 : "cc", "memory" \ 00243 ); \ 00244 _zzq_rlval = _zzq_result; \ 00245 } 00246 00247 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 00248 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 00249 volatile unsigned long long int __addr; \ 00250 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 00251 /* %RAX = guest_NRADDR */ \ 00252 "xchgq %%rcx,%%rcx" \ 00253 : "=a" (__addr) \ 00254 : \ 00255 : "cc", "memory" \ 00256 ); \ 00257 _zzq_orig->nraddr = __addr; \ 00258 } 00259 00260 #define VALGRIND_CALL_NOREDIR_RAX \ 00261 __SPECIAL_INSTRUCTION_PREAMBLE \ 00262 /* call-noredir *%RAX */ \ 00263 "xchgq %%rdx,%%rdx\n\t" 00264 #endif /* PLAT_amd64_linux */ 00265 00266 /* ------------------------ ppc32-linux ------------------------ */ 00267 00268 #if defined(PLAT_ppc32_linux) 00269 00270 typedef 00271 struct { 00272 unsigned int nraddr; /* where's the code? */ 00273 } 00274 OrigFn; 00275 00276 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 00277 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ 00278 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" 00279 00280 #define VALGRIND_DO_CLIENT_REQUEST( \ 00281 _zzq_rlval, _zzq_default, _zzq_request, \ 00282 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 00283 \ 00284 { unsigned int _zzq_args[6]; \ 00285 unsigned int _zzq_result; \ 00286 unsigned int* _zzq_ptr; \ 00287 _zzq_args[0] = (unsigned int)(_zzq_request); \ 00288 _zzq_args[1] = (unsigned int)(_zzq_arg1); \ 00289 _zzq_args[2] = (unsigned int)(_zzq_arg2); \ 00290 _zzq_args[3] = (unsigned int)(_zzq_arg3); \ 00291 _zzq_args[4] = (unsigned int)(_zzq_arg4); \ 00292 _zzq_args[5] = (unsigned int)(_zzq_arg5); \ 00293 _zzq_ptr = _zzq_args; \ 00294 __asm__ volatile("mr 3,%1\n\t" /*default*/ \ 00295 "mr 4,%2\n\t" /*ptr*/ \ 00296 __SPECIAL_INSTRUCTION_PREAMBLE \ 00297 /* %R3 = client_request ( %R4 ) */ \ 00298 "or 1,1,1\n\t" \ 00299 "mr %0,3" /*result*/ \ 00300 : "=b" (_zzq_result) \ 00301 : "b" (_zzq_default), "b" (_zzq_ptr) \ 00302 : "cc", "memory", "r3", "r4"); \ 00303 _zzq_rlval = _zzq_result; \ 00304 } 00305 00306 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 00307 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 00308 unsigned int __addr; \ 00309 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 00310 /* %R3 = guest_NRADDR */ \ 00311 "or 2,2,2\n\t" \ 00312 "mr %0,3" \ 00313 : "=b" (__addr) \ 00314 : \ 00315 : "cc", "memory", "r3" \ 00316 ); \ 00317 _zzq_orig->nraddr = __addr; \ 00318 } 00319 00320 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 00321 __SPECIAL_INSTRUCTION_PREAMBLE \ 00322 /* branch-and-link-to-noredir *%R11 */ \ 00323 "or 3,3,3\n\t" 00324 #endif /* PLAT_ppc32_linux */ 00325 00326 /* ------------------------ ppc64-linux ------------------------ */ 00327 00328 #if defined(PLAT_ppc64_linux) 00329 00330 typedef 00331 struct { 00332 unsigned long long int nraddr; /* where's the code? */ 00333 unsigned long long int r2; /* what tocptr do we need? */ 00334 } 00335 OrigFn; 00336 00337 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 00338 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ 00339 "rotldi 0,0,61 ; rotldi 0,0,51\n\t" 00340 00341 #define VALGRIND_DO_CLIENT_REQUEST( \ 00342 _zzq_rlval, _zzq_default, _zzq_request, \ 00343 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 00344 \ 00345 { unsigned long long int _zzq_args[6]; \ 00346 register unsigned long long int _zzq_result __asm__("r3"); \ 00347 register unsigned long long int* _zzq_ptr __asm__("r4"); \ 00348 _zzq_args[0] = (unsigned long long int)(_zzq_request); \ 00349 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ 00350 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ 00351 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ 00352 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ 00353 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ 00354 _zzq_ptr = _zzq_args; \ 00355 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 00356 /* %R3 = client_request ( %R4 ) */ \ 00357 "or 1,1,1" \ 00358 : "=r" (_zzq_result) \ 00359 : "0" (_zzq_default), "r" (_zzq_ptr) \ 00360 : "cc", "memory"); \ 00361 _zzq_rlval = _zzq_result; \ 00362 } 00363 00364 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 00365 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 00366 register unsigned long long int __addr __asm__("r3"); \ 00367 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 00368 /* %R3 = guest_NRADDR */ \ 00369 "or 2,2,2" \ 00370 : "=r" (__addr) \ 00371 : \ 00372 : "cc", "memory" \ 00373 ); \ 00374 _zzq_orig->nraddr = __addr; \ 00375 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 00376 /* %R3 = guest_NRADDR_GPR2 */ \ 00377 "or 4,4,4" \ 00378 : "=r" (__addr) \ 00379 : \ 00380 : "cc", "memory" \ 00381 ); \ 00382 _zzq_orig->r2 = __addr; \ 00383 } 00384 00385 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 00386 __SPECIAL_INSTRUCTION_PREAMBLE \ 00387 /* branch-and-link-to-noredir *%R11 */ \ 00388 "or 3,3,3\n\t" 00389 00390 #endif /* PLAT_ppc64_linux */ 00391 00392 /* ------------------------ ppc32-aix5 ------------------------- */ 00393 00394 #if defined(PLAT_ppc32_aix5) 00395 00396 typedef 00397 struct { 00398 unsigned int nraddr; /* where's the code? */ 00399 unsigned int r2; /* what tocptr do we need? */ 00400 } 00401 OrigFn; 00402 00403 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 00404 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ 00405 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" 00406 00407 #define VALGRIND_DO_CLIENT_REQUEST( \ 00408 _zzq_rlval, _zzq_default, _zzq_request, \ 00409 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 00410 \ 00411 { unsigned int _zzq_args[7]; \ 00412 register unsigned int _zzq_result; \ 00413 register unsigned int* _zzq_ptr; \ 00414 _zzq_args[0] = (unsigned int)(_zzq_request); \ 00415 _zzq_args[1] = (unsigned int)(_zzq_arg1); \ 00416 _zzq_args[2] = (unsigned int)(_zzq_arg2); \ 00417 _zzq_args[3] = (unsigned int)(_zzq_arg3); \ 00418 _zzq_args[4] = (unsigned int)(_zzq_arg4); \ 00419 _zzq_args[5] = (unsigned int)(_zzq_arg5); \ 00420 _zzq_args[6] = (unsigned int)(_zzq_default); \ 00421 _zzq_ptr = _zzq_args; \ 00422 __asm__ volatile("mr 4,%1\n\t" \ 00423 "lwz 3, 24(4)\n\t" \ 00424 __SPECIAL_INSTRUCTION_PREAMBLE \ 00425 /* %R3 = client_request ( %R4 ) */ \ 00426 "or 1,1,1\n\t" \ 00427 "mr %0,3" \ 00428 : "=b" (_zzq_result) \ 00429 : "b" (_zzq_ptr) \ 00430 : "r3", "r4", "cc", "memory"); \ 00431 _zzq_rlval = _zzq_result; \ 00432 } 00433 00434 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 00435 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 00436 register unsigned int __addr; \ 00437 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 00438 /* %R3 = guest_NRADDR */ \ 00439 "or 2,2,2\n\t" \ 00440 "mr %0,3" \ 00441 : "=b" (__addr) \ 00442 : \ 00443 : "r3", "cc", "memory" \ 00444 ); \ 00445 _zzq_orig->nraddr = __addr; \ 00446 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 00447 /* %R3 = guest_NRADDR_GPR2 */ \ 00448 "or 4,4,4\n\t" \ 00449 "mr %0,3" \ 00450 : "=b" (__addr) \ 00451 : \ 00452 : "r3", "cc", "memory" \ 00453 ); \ 00454 _zzq_orig->r2 = __addr; \ 00455 } 00456 00457 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 00458 __SPECIAL_INSTRUCTION_PREAMBLE \ 00459 /* branch-and-link-to-noredir *%R11 */ \ 00460 "or 3,3,3\n\t" 00461 00462 #endif /* PLAT_ppc32_aix5 */ 00463 00464 /* ------------------------ ppc64-aix5 ------------------------- */ 00465 00466 #if defined(PLAT_ppc64_aix5) 00467 00468 typedef 00469 struct { 00470 unsigned long long int nraddr; /* where's the code? */ 00471 unsigned long long int r2; /* what tocptr do we need? */ 00472 } 00473 OrigFn; 00474 00475 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 00476 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ 00477 "rotldi 0,0,61 ; rotldi 0,0,51\n\t" 00478 00479 #define VALGRIND_DO_CLIENT_REQUEST( \ 00480 _zzq_rlval, _zzq_default, _zzq_request, \ 00481 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 00482 \ 00483 { unsigned long long int _zzq_args[7]; \ 00484 register unsigned long long int _zzq_result; \ 00485 register unsigned long long int* _zzq_ptr; \ 00486 _zzq_args[0] = (unsigned int long long)(_zzq_request); \ 00487 _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \ 00488 _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \ 00489 _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \ 00490 _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \ 00491 _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \ 00492 _zzq_args[6] = (unsigned int long long)(_zzq_default); \ 00493 _zzq_ptr = _zzq_args; \ 00494 __asm__ volatile("mr 4,%1\n\t" \ 00495 "ld 3, 48(4)\n\t" \ 00496 __SPECIAL_INSTRUCTION_PREAMBLE \ 00497 /* %R3 = client_request ( %R4 ) */ \ 00498 "or 1,1,1\n\t" \ 00499 "mr %0,3" \ 00500 : "=b" (_zzq_result) \ 00501 : "b" (_zzq_ptr) \ 00502 : "r3", "r4", "cc", "memory"); \ 00503 _zzq_rlval = _zzq_result; \ 00504 } 00505 00506 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 00507 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 00508 register unsigned long long int __addr; \ 00509 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 00510 /* %R3 = guest_NRADDR */ \ 00511 "or 2,2,2\n\t" \ 00512 "mr %0,3" \ 00513 : "=b" (__addr) \ 00514 : \ 00515 : "r3", "cc", "memory" \ 00516 ); \ 00517 _zzq_orig->nraddr = __addr; \ 00518 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 00519 /* %R3 = guest_NRADDR_GPR2 */ \ 00520 "or 4,4,4\n\t" \ 00521 "mr %0,3" \ 00522 : "=b" (__addr) \ 00523 : \ 00524 : "r3", "cc", "memory" \ 00525 ); \ 00526 _zzq_orig->r2 = __addr; \ 00527 } 00528 00529 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 00530 __SPECIAL_INSTRUCTION_PREAMBLE \ 00531 /* branch-and-link-to-noredir *%R11 */ \ 00532 "or 3,3,3\n\t" 00533 00534 #endif /* PLAT_ppc64_aix5 */ 00535 00536 /* Insert assembly code for other platforms here... */ 00537 00538 #endif /* NVALGRIND */ 00539 00540 00541 /* ------------------------------------------------------------------ */ 00542 /* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */ 00543 /* ugly. It's the least-worst tradeoff I can think of. */ 00544 /* ------------------------------------------------------------------ */ 00545 00546 /* This section defines magic (a.k.a appalling-hack) macros for doing 00547 guaranteed-no-redirection macros, so as to get from function 00548 wrappers to the functions they are wrapping. The whole point is to 00549 construct standard call sequences, but to do the call itself with a 00550 special no-redirect call pseudo-instruction that the JIT 00551 understands and handles specially. This section is long and 00552 repetitious, and I can't see a way to make it shorter. 00553 00554 The naming scheme is as follows: 00555 00556 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc} 00557 00558 'W' stands for "word" and 'v' for "void". Hence there are 00559 different macros for calling arity 0, 1, 2, 3, 4, etc, functions, 00560 and for each, the possibility of returning a word-typed result, or 00561 no result. 00562 */ 00563 00564 /* Use these to write the name of your wrapper. NOTE: duplicates 00565 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */ 00566 00567 #define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \ 00568 _vgwZU_##soname##_##fnname 00569 00570 #define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \ 00571 _vgwZZ_##soname##_##fnname 00572 00573 /* Use this macro from within a wrapper function to collect the 00574 context (address and possibly other info) of the original function. 00575 Once you have that you can then use it in one of the CALL_FN_ 00576 macros. The type of the argument _lval is OrigFn. */ 00577 #define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval) 00578 00579 /* Derivatives of the main macros below, for calling functions 00580 returning void. */ 00581 00582 #define CALL_FN_v_v(fnptr) \ 00583 do { volatile unsigned long _junk; \ 00584 CALL_FN_W_v(_junk,fnptr); } while (0) 00585 00586 #define CALL_FN_v_W(fnptr, arg1) \ 00587 do { volatile unsigned long _junk; \ 00588 CALL_FN_W_W(_junk,fnptr,arg1); } while (0) 00589 00590 #define CALL_FN_v_WW(fnptr, arg1,arg2) \ 00591 do { volatile unsigned long _junk; \ 00592 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0) 00593 00594 #define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \ 00595 do { volatile unsigned long _junk; \ 00596 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0) 00597 00598 /* ------------------------- x86-linux ------------------------- */ 00599 00600 #if defined(PLAT_x86_linux) 00601 00602 /* These regs are trashed by the hidden call. No need to mention eax 00603 as gcc can already see that, plus causes gcc to bomb. */ 00604 #define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx" 00605 00606 /* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned 00607 long) == 4. */ 00608 00609 #define CALL_FN_W_v(lval, orig) \ 00610 do { \ 00611 volatile OrigFn _orig = (orig); \ 00612 volatile unsigned long _argvec[1]; \ 00613 volatile unsigned long _res; \ 00614 _argvec[0] = (unsigned long)_orig.nraddr; \ 00615 __asm__ volatile( \ 00616 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 00617 VALGRIND_CALL_NOREDIR_EAX \ 00618 : /*out*/ "=a" (_res) \ 00619 : /*in*/ "a" (&_argvec[0]) \ 00620 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 00621 ); \ 00622 lval = (__typeof__(lval)) _res; \ 00623 } while (0) 00624 00625 #define CALL_FN_W_W(lval, orig, arg1) \ 00626 do { \ 00627 volatile OrigFn _orig = (orig); \ 00628 volatile unsigned long _argvec[2]; \ 00629 volatile unsigned long _res; \ 00630 _argvec[0] = (unsigned long)_orig.nraddr; \ 00631 _argvec[1] = (unsigned long)(arg1); \ 00632 __asm__ volatile( \ 00633 "pushl 4(%%eax)\n\t" \ 00634 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 00635 VALGRIND_CALL_NOREDIR_EAX \ 00636 "addl $4, %%esp\n" \ 00637 : /*out*/ "=a" (_res) \ 00638 : /*in*/ "a" (&_argvec[0]) \ 00639 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 00640 ); \ 00641 lval = (__typeof__(lval)) _res; \ 00642 } while (0) 00643 00644 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 00645 do { \ 00646 volatile OrigFn _orig = (orig); \ 00647 volatile unsigned long _argvec[3]; \ 00648 volatile unsigned long _res; \ 00649 _argvec[0] = (unsigned long)_orig.nraddr; \ 00650 _argvec[1] = (unsigned long)(arg1); \ 00651 _argvec[2] = (unsigned long)(arg2); \ 00652 __asm__ volatile( \ 00653 "pushl 8(%%eax)\n\t" \ 00654 "pushl 4(%%eax)\n\t" \ 00655 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 00656 VALGRIND_CALL_NOREDIR_EAX \ 00657 "addl $8, %%esp\n" \ 00658 : /*out*/ "=a" (_res) \ 00659 : /*in*/ "a" (&_argvec[0]) \ 00660 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 00661 ); \ 00662 lval = (__typeof__(lval)) _res; \ 00663 } while (0) 00664 00665 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 00666 do { \ 00667 volatile OrigFn _orig = (orig); \ 00668 volatile unsigned long _argvec[4]; \ 00669 volatile unsigned long _res; \ 00670 _argvec[0] = (unsigned long)_orig.nraddr; \ 00671 _argvec[1] = (unsigned long)(arg1); \ 00672 _argvec[2] = (unsigned long)(arg2); \ 00673 _argvec[3] = (unsigned long)(arg3); \ 00674 __asm__ volatile( \ 00675 "pushl 12(%%eax)\n\t" \ 00676 "pushl 8(%%eax)\n\t" \ 00677 "pushl 4(%%eax)\n\t" \ 00678 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 00679 VALGRIND_CALL_NOREDIR_EAX \ 00680 "addl $12, %%esp\n" \ 00681 : /*out*/ "=a" (_res) \ 00682 : /*in*/ "a" (&_argvec[0]) \ 00683 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 00684 ); \ 00685 lval = (__typeof__(lval)) _res; \ 00686 } while (0) 00687 00688 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 00689 do { \ 00690 volatile OrigFn _orig = (orig); \ 00691 volatile unsigned long _argvec[5]; \ 00692 volatile unsigned long _res; \ 00693 _argvec[0] = (unsigned long)_orig.nraddr; \ 00694 _argvec[1] = (unsigned long)(arg1); \ 00695 _argvec[2] = (unsigned long)(arg2); \ 00696 _argvec[3] = (unsigned long)(arg3); \ 00697 _argvec[4] = (unsigned long)(arg4); \ 00698 __asm__ volatile( \ 00699 "pushl 16(%%eax)\n\t" \ 00700 "pushl 12(%%eax)\n\t" \ 00701 "pushl 8(%%eax)\n\t" \ 00702 "pushl 4(%%eax)\n\t" \ 00703 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 00704 VALGRIND_CALL_NOREDIR_EAX \ 00705 "addl $16, %%esp\n" \ 00706 : /*out*/ "=a" (_res) \ 00707 : /*in*/ "a" (&_argvec[0]) \ 00708 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 00709 ); \ 00710 lval = (__typeof__(lval)) _res; \ 00711 } while (0) 00712 00713 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 00714 do { \ 00715 volatile OrigFn _orig = (orig); \ 00716 volatile unsigned long _argvec[6]; \ 00717 volatile unsigned long _res; \ 00718 _argvec[0] = (unsigned long)_orig.nraddr; \ 00719 _argvec[1] = (unsigned long)(arg1); \ 00720 _argvec[2] = (unsigned long)(arg2); \ 00721 _argvec[3] = (unsigned long)(arg3); \ 00722 _argvec[4] = (unsigned long)(arg4); \ 00723 _argvec[5] = (unsigned long)(arg5); \ 00724 __asm__ volatile( \ 00725 "pushl 20(%%eax)\n\t" \ 00726 "pushl 16(%%eax)\n\t" \ 00727 "pushl 12(%%eax)\n\t" \ 00728 "pushl 8(%%eax)\n\t" \ 00729 "pushl 4(%%eax)\n\t" \ 00730 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 00731 VALGRIND_CALL_NOREDIR_EAX \ 00732 "addl $20, %%esp\n" \ 00733 : /*out*/ "=a" (_res) \ 00734 : /*in*/ "a" (&_argvec[0]) \ 00735 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 00736 ); \ 00737 lval = (__typeof__(lval)) _res; \ 00738 } while (0) 00739 00740 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 00741 do { \ 00742 volatile OrigFn _orig = (orig); \ 00743 volatile unsigned long _argvec[7]; \ 00744 volatile unsigned long _res; \ 00745 _argvec[0] = (unsigned long)_orig.nraddr; \ 00746 _argvec[1] = (unsigned long)(arg1); \ 00747 _argvec[2] = (unsigned long)(arg2); \ 00748 _argvec[3] = (unsigned long)(arg3); \ 00749 _argvec[4] = (unsigned long)(arg4); \ 00750 _argvec[5] = (unsigned long)(arg5); \ 00751 _argvec[6] = (unsigned long)(arg6); \ 00752 __asm__ volatile( \ 00753 "pushl 24(%%eax)\n\t" \ 00754 "pushl 20(%%eax)\n\t" \ 00755 "pushl 16(%%eax)\n\t" \ 00756 "pushl 12(%%eax)\n\t" \ 00757 "pushl 8(%%eax)\n\t" \ 00758 "pushl 4(%%eax)\n\t" \ 00759 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 00760 VALGRIND_CALL_NOREDIR_EAX \ 00761 "addl $24, %%esp\n" \ 00762 : /*out*/ "=a" (_res) \ 00763 : /*in*/ "a" (&_argvec[0]) \ 00764 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 00765 ); \ 00766 lval = (__typeof__(lval)) _res; \ 00767 } while (0) 00768 00769 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 00770 arg7) \ 00771 do { \ 00772 volatile OrigFn _orig = (orig); \ 00773 volatile unsigned long _argvec[8]; \ 00774 volatile unsigned long _res; \ 00775 _argvec[0] = (unsigned long)_orig.nraddr; \ 00776 _argvec[1] = (unsigned long)(arg1); \ 00777 _argvec[2] = (unsigned long)(arg2); \ 00778 _argvec[3] = (unsigned long)(arg3); \ 00779 _argvec[4] = (unsigned long)(arg4); \ 00780 _argvec[5] = (unsigned long)(arg5); \ 00781 _argvec[6] = (unsigned long)(arg6); \ 00782 _argvec[7] = (unsigned long)(arg7); \ 00783 __asm__ volatile( \ 00784 "pushl 28(%%eax)\n\t" \ 00785 "pushl 24(%%eax)\n\t" \ 00786 "pushl 20(%%eax)\n\t" \ 00787 "pushl 16(%%eax)\n\t" \ 00788 "pushl 12(%%eax)\n\t" \ 00789 "pushl 8(%%eax)\n\t" \ 00790 "pushl 4(%%eax)\n\t" \ 00791 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 00792 VALGRIND_CALL_NOREDIR_EAX \ 00793 "addl $28, %%esp\n" \ 00794 : /*out*/ "=a" (_res) \ 00795 : /*in*/ "a" (&_argvec[0]) \ 00796 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 00797 ); \ 00798 lval = (__typeof__(lval)) _res; \ 00799 } while (0) 00800 00801 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 00802 arg7,arg8) \ 00803 do { \ 00804 volatile OrigFn _orig = (orig); \ 00805 volatile unsigned long _argvec[9]; \ 00806 volatile unsigned long _res; \ 00807 _argvec[0] = (unsigned long)_orig.nraddr; \ 00808 _argvec[1] = (unsigned long)(arg1); \ 00809 _argvec[2] = (unsigned long)(arg2); \ 00810 _argvec[3] = (unsigned long)(arg3); \ 00811 _argvec[4] = (unsigned long)(arg4); \ 00812 _argvec[5] = (unsigned long)(arg5); \ 00813 _argvec[6] = (unsigned long)(arg6); \ 00814 _argvec[7] = (unsigned long)(arg7); \ 00815 _argvec[8] = (unsigned long)(arg8); \ 00816 __asm__ volatile( \ 00817 "pushl 32(%%eax)\n\t" \ 00818 "pushl 28(%%eax)\n\t" \ 00819 "pushl 24(%%eax)\n\t" \ 00820 "pushl 20(%%eax)\n\t" \ 00821 "pushl 16(%%eax)\n\t" \ 00822 "pushl 12(%%eax)\n\t" \ 00823 "pushl 8(%%eax)\n\t" \ 00824 "pushl 4(%%eax)\n\t" \ 00825 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 00826 VALGRIND_CALL_NOREDIR_EAX \ 00827 "addl $32, %%esp\n" \ 00828 : /*out*/ "=a" (_res) \ 00829 : /*in*/ "a" (&_argvec[0]) \ 00830 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 00831 ); \ 00832 lval = (__typeof__(lval)) _res; \ 00833 } while (0) 00834 00835 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 00836 arg7,arg8,arg9) \ 00837 do { \ 00838 volatile OrigFn _orig = (orig); \ 00839 volatile unsigned long _argvec[10]; \ 00840 volatile unsigned long _res; \ 00841 _argvec[0] = (unsigned long)_orig.nraddr; \ 00842 _argvec[1] = (unsigned long)(arg1); \ 00843 _argvec[2] = (unsigned long)(arg2); \ 00844 _argvec[3] = (unsigned long)(arg3); \ 00845 _argvec[4] = (unsigned long)(arg4); \ 00846 _argvec[5] = (unsigned long)(arg5); \ 00847 _argvec[6] = (unsigned long)(arg6); \ 00848 _argvec[7] = (unsigned long)(arg7); \ 00849 _argvec[8] = (unsigned long)(arg8); \ 00850 _argvec[9] = (unsigned long)(arg9); \ 00851 __asm__ volatile( \ 00852 "pushl 36(%%eax)\n\t" \ 00853 "pushl 32(%%eax)\n\t" \ 00854 "pushl 28(%%eax)\n\t" \ 00855 "pushl 24(%%eax)\n\t" \ 00856 "pushl 20(%%eax)\n\t" \ 00857 "pushl 16(%%eax)\n\t" \ 00858 "pushl 12(%%eax)\n\t" \ 00859 "pushl 8(%%eax)\n\t" \ 00860 "pushl 4(%%eax)\n\t" \ 00861 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 00862 VALGRIND_CALL_NOREDIR_EAX \ 00863 "addl $36, %%esp\n" \ 00864 : /*out*/ "=a" (_res) \ 00865 : /*in*/ "a" (&_argvec[0]) \ 00866 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 00867 ); \ 00868 lval = (__typeof__(lval)) _res; \ 00869 } while (0) 00870 00871 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 00872 arg7,arg8,arg9,arg10) \ 00873 do { \ 00874 volatile OrigFn _orig = (orig); \ 00875 volatile unsigned long _argvec[11]; \ 00876 volatile unsigned long _res; \ 00877 _argvec[0] = (unsigned long)_orig.nraddr; \ 00878 _argvec[1] = (unsigned long)(arg1); \ 00879 _argvec[2] = (unsigned long)(arg2); \ 00880 _argvec[3] = (unsigned long)(arg3); \ 00881 _argvec[4] = (unsigned long)(arg4); \ 00882 _argvec[5] = (unsigned long)(arg5); \ 00883 _argvec[6] = (unsigned long)(arg6); \ 00884 _argvec[7] = (unsigned long)(arg7); \ 00885 _argvec[8] = (unsigned long)(arg8); \ 00886 _argvec[9] = (unsigned long)(arg9); \ 00887 _argvec[10] = (unsigned long)(arg10); \ 00888 __asm__ volatile( \ 00889 "pushl 40(%%eax)\n\t" \ 00890 "pushl 36(%%eax)\n\t" \ 00891 "pushl 32(%%eax)\n\t" \ 00892 "pushl 28(%%eax)\n\t" \ 00893 "pushl 24(%%eax)\n\t" \ 00894 "pushl 20(%%eax)\n\t" \ 00895 "pushl 16(%%eax)\n\t" \ 00896 "pushl 12(%%eax)\n\t" \ 00897 "pushl 8(%%eax)\n\t" \ 00898 "pushl 4(%%eax)\n\t" \ 00899 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 00900 VALGRIND_CALL_NOREDIR_EAX \ 00901 "addl $40, %%esp\n" \ 00902 : /*out*/ "=a" (_res) \ 00903 : /*in*/ "a" (&_argvec[0]) \ 00904 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 00905 ); \ 00906 lval = (__typeof__(lval)) _res; \ 00907 } while (0) 00908 00909 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ 00910 arg6,arg7,arg8,arg9,arg10, \ 00911 arg11) \ 00912 do { \ 00913 volatile OrigFn _orig = (orig); \ 00914 volatile unsigned long _argvec[12]; \ 00915 volatile unsigned long _res; \ 00916 _argvec[0] = (unsigned long)_orig.nraddr; \ 00917 _argvec[1] = (unsigned long)(arg1); \ 00918 _argvec[2] = (unsigned long)(arg2); \ 00919 _argvec[3] = (unsigned long)(arg3); \ 00920 _argvec[4] = (unsigned long)(arg4); \ 00921 _argvec[5] = (unsigned long)(arg5); \ 00922 _argvec[6] = (unsigned long)(arg6); \ 00923 _argvec[7] = (unsigned long)(arg7); \ 00924 _argvec[8] = (unsigned long)(arg8); \ 00925 _argvec[9] = (unsigned long)(arg9); \ 00926 _argvec[10] = (unsigned long)(arg10); \ 00927 _argvec[11] = (unsigned long)(arg11); \ 00928 __asm__ volatile( \ 00929 "pushl 44(%%eax)\n\t" \ 00930 "pushl 40(%%eax)\n\t" \ 00931 "pushl 36(%%eax)\n\t" \ 00932 "pushl 32(%%eax)\n\t" \ 00933 "pushl 28(%%eax)\n\t" \ 00934 "pushl 24(%%eax)\n\t" \ 00935 "pushl 20(%%eax)\n\t" \ 00936 "pushl 16(%%eax)\n\t" \ 00937 "pushl 12(%%eax)\n\t" \ 00938 "pushl 8(%%eax)\n\t" \ 00939 "pushl 4(%%eax)\n\t" \ 00940 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 00941 VALGRIND_CALL_NOREDIR_EAX \ 00942 "addl $44, %%esp\n" \ 00943 : /*out*/ "=a" (_res) \ 00944 : /*in*/ "a" (&_argvec[0]) \ 00945 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 00946 ); \ 00947 lval = (__typeof__(lval)) _res; \ 00948 } while (0) 00949 00950 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ 00951 arg6,arg7,arg8,arg9,arg10, \ 00952 arg11,arg12) \ 00953 do { \ 00954 volatile OrigFn _orig = (orig); \ 00955 volatile unsigned long _argvec[13]; \ 00956 volatile unsigned long _res; \ 00957 _argvec[0] = (unsigned long)_orig.nraddr; \ 00958 _argvec[1] = (unsigned long)(arg1); \ 00959 _argvec[2] = (unsigned long)(arg2); \ 00960 _argvec[3] = (unsigned long)(arg3); \ 00961 _argvec[4] = (unsigned long)(arg4); \ 00962 _argvec[5] = (unsigned long)(arg5); \ 00963 _argvec[6] = (unsigned long)(arg6); \ 00964 _argvec[7] = (unsigned long)(arg7); \ 00965 _argvec[8] = (unsigned long)(arg8); \ 00966 _argvec[9] = (unsigned long)(arg9); \ 00967 _argvec[10] = (unsigned long)(arg10); \ 00968 _argvec[11] = (unsigned long)(arg11); \ 00969 _argvec[12] = (unsigned long)(arg12); \ 00970 __asm__ volatile( \ 00971 "pushl 48(%%eax)\n\t" \ 00972 "pushl 44(%%eax)\n\t" \ 00973 "pushl 40(%%eax)\n\t" \ 00974 "pushl 36(%%eax)\n\t" \ 00975 "pushl 32(%%eax)\n\t" \ 00976 "pushl 28(%%eax)\n\t" \ 00977 "pushl 24(%%eax)\n\t" \ 00978 "pushl 20(%%eax)\n\t" \ 00979 "pushl 16(%%eax)\n\t" \ 00980 "pushl 12(%%eax)\n\t" \ 00981 "pushl 8(%%eax)\n\t" \ 00982 "pushl 4(%%eax)\n\t" \ 00983 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 00984 VALGRIND_CALL_NOREDIR_EAX \ 00985 "addl $48, %%esp\n" \ 00986 : /*out*/ "=a" (_res) \ 00987 : /*in*/ "a" (&_argvec[0]) \ 00988 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 00989 ); \ 00990 lval = (__typeof__(lval)) _res; \ 00991 } while (0) 00992 00993 #endif /* PLAT_x86_linux */ 00994 00995 /* ------------------------ amd64-linux ------------------------ */ 00996 00997 #if defined(PLAT_amd64_linux) 00998 00999 /* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */ 01000 01001 /* These regs are trashed by the hidden call. */ 01002 #define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \ 01003 "rdi", "r8", "r9", "r10", "r11" 01004 01005 /* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned 01006 long) == 8. */ 01007 01008 /* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_ 01009 macros. In order not to trash the stack redzone, we need to drop 01010 %rsp by 128 before the hidden call, and restore afterwards. The 01011 nastyness is that it is only by luck that the stack still appears 01012 to be unwindable during the hidden call - since then the behaviour 01013 of any routine using this macro does not match what the CFI data 01014 says. Sigh. 01015 01016 Why is this important? Imagine that a wrapper has a stack 01017 allocated local, and passes to the hidden call, a pointer to it. 01018 Because gcc does not know about the hidden call, it may allocate 01019 that local in the redzone. Unfortunately the hidden call may then 01020 trash it before it comes to use it. So we must step clear of the 01021 redzone, for the duration of the hidden call, to make it safe. 01022 01023 Probably the same problem afflicts the other redzone-style ABIs too 01024 (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is 01025 self describing (none of this CFI nonsense) so at least messing 01026 with the stack pointer doesn't give a danger of non-unwindable 01027 stack. */ 01028 01029 #define CALL_FN_W_v(lval, orig) \ 01030 do { \ 01031 volatile OrigFn _orig = (orig); \ 01032 volatile unsigned long _argvec[1]; \ 01033 volatile unsigned long _res; \ 01034 _argvec[0] = (unsigned long)_orig.nraddr; \ 01035 __asm__ volatile( \ 01036 "subq $128,%%rsp\n\t" \ 01037 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 01038 VALGRIND_CALL_NOREDIR_RAX \ 01039 "addq $128,%%rsp\n\t" \ 01040 : /*out*/ "=a" (_res) \ 01041 : /*in*/ "a" (&_argvec[0]) \ 01042 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01043 ); \ 01044 lval = (__typeof__(lval)) _res; \ 01045 } while (0) 01046 01047 #define CALL_FN_W_W(lval, orig, arg1) \ 01048 do { \ 01049 volatile OrigFn _orig = (orig); \ 01050 volatile unsigned long _argvec[2]; \ 01051 volatile unsigned long _res; \ 01052 _argvec[0] = (unsigned long)_orig.nraddr; \ 01053 _argvec[1] = (unsigned long)(arg1); \ 01054 __asm__ volatile( \ 01055 "subq $128,%%rsp\n\t" \ 01056 "movq 8(%%rax), %%rdi\n\t" \ 01057 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 01058 VALGRIND_CALL_NOREDIR_RAX \ 01059 "addq $128,%%rsp\n\t" \ 01060 : /*out*/ "=a" (_res) \ 01061 : /*in*/ "a" (&_argvec[0]) \ 01062 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01063 ); \ 01064 lval = (__typeof__(lval)) _res; \ 01065 } while (0) 01066 01067 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 01068 do { \ 01069 volatile OrigFn _orig = (orig); \ 01070 volatile unsigned long _argvec[3]; \ 01071 volatile unsigned long _res; \ 01072 _argvec[0] = (unsigned long)_orig.nraddr; \ 01073 _argvec[1] = (unsigned long)(arg1); \ 01074 _argvec[2] = (unsigned long)(arg2); \ 01075 __asm__ volatile( \ 01076 "subq $128,%%rsp\n\t" \ 01077 "movq 16(%%rax), %%rsi\n\t" \ 01078 "movq 8(%%rax), %%rdi\n\t" \ 01079 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 01080 VALGRIND_CALL_NOREDIR_RAX \ 01081 "addq $128,%%rsp\n\t" \ 01082 : /*out*/ "=a" (_res) \ 01083 : /*in*/ "a" (&_argvec[0]) \ 01084 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01085 ); \ 01086 lval = (__typeof__(lval)) _res; \ 01087 } while (0) 01088 01089 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 01090 do { \ 01091 volatile OrigFn _orig = (orig); \ 01092 volatile unsigned long _argvec[4]; \ 01093 volatile unsigned long _res; \ 01094 _argvec[0] = (unsigned long)_orig.nraddr; \ 01095 _argvec[1] = (unsigned long)(arg1); \ 01096 _argvec[2] = (unsigned long)(arg2); \ 01097 _argvec[3] = (unsigned long)(arg3); \ 01098 __asm__ volatile( \ 01099 "subq $128,%%rsp\n\t" \ 01100 "movq 24(%%rax), %%rdx\n\t" \ 01101 "movq 16(%%rax), %%rsi\n\t" \ 01102 "movq 8(%%rax), %%rdi\n\t" \ 01103 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 01104 VALGRIND_CALL_NOREDIR_RAX \ 01105 "addq $128,%%rsp\n\t" \ 01106 : /*out*/ "=a" (_res) \ 01107 : /*in*/ "a" (&_argvec[0]) \ 01108 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01109 ); \ 01110 lval = (__typeof__(lval)) _res; \ 01111 } while (0) 01112 01113 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 01114 do { \ 01115 volatile OrigFn _orig = (orig); \ 01116 volatile unsigned long _argvec[5]; \ 01117 volatile unsigned long _res; \ 01118 _argvec[0] = (unsigned long)_orig.nraddr; \ 01119 _argvec[1] = (unsigned long)(arg1); \ 01120 _argvec[2] = (unsigned long)(arg2); \ 01121 _argvec[3] = (unsigned long)(arg3); \ 01122 _argvec[4] = (unsigned long)(arg4); \ 01123 __asm__ volatile( \ 01124 "subq $128,%%rsp\n\t" \ 01125 "movq 32(%%rax), %%rcx\n\t" \ 01126 "movq 24(%%rax), %%rdx\n\t" \ 01127 "movq 16(%%rax), %%rsi\n\t" \ 01128 "movq 8(%%rax), %%rdi\n\t" \ 01129 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 01130 VALGRIND_CALL_NOREDIR_RAX \ 01131 "addq $128,%%rsp\n\t" \ 01132 : /*out*/ "=a" (_res) \ 01133 : /*in*/ "a" (&_argvec[0]) \ 01134 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01135 ); \ 01136 lval = (__typeof__(lval)) _res; \ 01137 } while (0) 01138 01139 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 01140 do { \ 01141 volatile OrigFn _orig = (orig); \ 01142 volatile unsigned long _argvec[6]; \ 01143 volatile unsigned long _res; \ 01144 _argvec[0] = (unsigned long)_orig.nraddr; \ 01145 _argvec[1] = (unsigned long)(arg1); \ 01146 _argvec[2] = (unsigned long)(arg2); \ 01147 _argvec[3] = (unsigned long)(arg3); \ 01148 _argvec[4] = (unsigned long)(arg4); \ 01149 _argvec[5] = (unsigned long)(arg5); \ 01150 __asm__ volatile( \ 01151 "subq $128,%%rsp\n\t" \ 01152 "movq 40(%%rax), %%r8\n\t" \ 01153 "movq 32(%%rax), %%rcx\n\t" \ 01154 "movq 24(%%rax), %%rdx\n\t" \ 01155 "movq 16(%%rax), %%rsi\n\t" \ 01156 "movq 8(%%rax), %%rdi\n\t" \ 01157 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 01158 VALGRIND_CALL_NOREDIR_RAX \ 01159 "addq $128,%%rsp\n\t" \ 01160 : /*out*/ "=a" (_res) \ 01161 : /*in*/ "a" (&_argvec[0]) \ 01162 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01163 ); \ 01164 lval = (__typeof__(lval)) _res; \ 01165 } while (0) 01166 01167 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 01168 do { \ 01169 volatile OrigFn _orig = (orig); \ 01170 volatile unsigned long _argvec[7]; \ 01171 volatile unsigned long _res; \ 01172 _argvec[0] = (unsigned long)_orig.nraddr; \ 01173 _argvec[1] = (unsigned long)(arg1); \ 01174 _argvec[2] = (unsigned long)(arg2); \ 01175 _argvec[3] = (unsigned long)(arg3); \ 01176 _argvec[4] = (unsigned long)(arg4); \ 01177 _argvec[5] = (unsigned long)(arg5); \ 01178 _argvec[6] = (unsigned long)(arg6); \ 01179 __asm__ volatile( \ 01180 "subq $128,%%rsp\n\t" \ 01181 "movq 48(%%rax), %%r9\n\t" \ 01182 "movq 40(%%rax), %%r8\n\t" \ 01183 "movq 32(%%rax), %%rcx\n\t" \ 01184 "movq 24(%%rax), %%rdx\n\t" \ 01185 "movq 16(%%rax), %%rsi\n\t" \ 01186 "movq 8(%%rax), %%rdi\n\t" \ 01187 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 01188 "addq $128,%%rsp\n\t" \ 01189 VALGRIND_CALL_NOREDIR_RAX \ 01190 : /*out*/ "=a" (_res) \ 01191 : /*in*/ "a" (&_argvec[0]) \ 01192 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01193 ); \ 01194 lval = (__typeof__(lval)) _res; \ 01195 } while (0) 01196 01197 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 01198 arg7) \ 01199 do { \ 01200 volatile OrigFn _orig = (orig); \ 01201 volatile unsigned long _argvec[8]; \ 01202 volatile unsigned long _res; \ 01203 _argvec[0] = (unsigned long)_orig.nraddr; \ 01204 _argvec[1] = (unsigned long)(arg1); \ 01205 _argvec[2] = (unsigned long)(arg2); \ 01206 _argvec[3] = (unsigned long)(arg3); \ 01207 _argvec[4] = (unsigned long)(arg4); \ 01208 _argvec[5] = (unsigned long)(arg5); \ 01209 _argvec[6] = (unsigned long)(arg6); \ 01210 _argvec[7] = (unsigned long)(arg7); \ 01211 __asm__ volatile( \ 01212 "subq $128,%%rsp\n\t" \ 01213 "pushq 56(%%rax)\n\t" \ 01214 "movq 48(%%rax), %%r9\n\t" \ 01215 "movq 40(%%rax), %%r8\n\t" \ 01216 "movq 32(%%rax), %%rcx\n\t" \ 01217 "movq 24(%%rax), %%rdx\n\t" \ 01218 "movq 16(%%rax), %%rsi\n\t" \ 01219 "movq 8(%%rax), %%rdi\n\t" \ 01220 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 01221 VALGRIND_CALL_NOREDIR_RAX \ 01222 "addq $8, %%rsp\n" \ 01223 "addq $128,%%rsp\n\t" \ 01224 : /*out*/ "=a" (_res) \ 01225 : /*in*/ "a" (&_argvec[0]) \ 01226 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01227 ); \ 01228 lval = (__typeof__(lval)) _res; \ 01229 } while (0) 01230 01231 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 01232 arg7,arg8) \ 01233 do { \ 01234 volatile OrigFn _orig = (orig); \ 01235 volatile unsigned long _argvec[9]; \ 01236 volatile unsigned long _res; \ 01237 _argvec[0] = (unsigned long)_orig.nraddr; \ 01238 _argvec[1] = (unsigned long)(arg1); \ 01239 _argvec[2] = (unsigned long)(arg2); \ 01240 _argvec[3] = (unsigned long)(arg3); \ 01241 _argvec[4] = (unsigned long)(arg4); \ 01242 _argvec[5] = (unsigned long)(arg5); \ 01243 _argvec[6] = (unsigned long)(arg6); \ 01244 _argvec[7] = (unsigned long)(arg7); \ 01245 _argvec[8] = (unsigned long)(arg8); \ 01246 __asm__ volatile( \ 01247 "subq $128,%%rsp\n\t" \ 01248 "pushq 64(%%rax)\n\t" \ 01249 "pushq 56(%%rax)\n\t" \ 01250 "movq 48(%%rax), %%r9\n\t" \ 01251 "movq 40(%%rax), %%r8\n\t" \ 01252 "movq 32(%%rax), %%rcx\n\t" \ 01253 "movq 24(%%rax), %%rdx\n\t" \ 01254 "movq 16(%%rax), %%rsi\n\t" \ 01255 "movq 8(%%rax), %%rdi\n\t" \ 01256 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 01257 VALGRIND_CALL_NOREDIR_RAX \ 01258 "addq $16, %%rsp\n" \ 01259 "addq $128,%%rsp\n\t" \ 01260 : /*out*/ "=a" (_res) \ 01261 : /*in*/ "a" (&_argvec[0]) \ 01262 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01263 ); \ 01264 lval = (__typeof__(lval)) _res; \ 01265 } while (0) 01266 01267 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 01268 arg7,arg8,arg9) \ 01269 do { \ 01270 volatile OrigFn _orig = (orig); \ 01271 volatile unsigned long _argvec[10]; \ 01272 volatile unsigned long _res; \ 01273 _argvec[0] = (unsigned long)_orig.nraddr; \ 01274 _argvec[1] = (unsigned long)(arg1); \ 01275 _argvec[2] = (unsigned long)(arg2); \ 01276 _argvec[3] = (unsigned long)(arg3); \ 01277 _argvec[4] = (unsigned long)(arg4); \ 01278 _argvec[5] = (unsigned long)(arg5); \ 01279 _argvec[6] = (unsigned long)(arg6); \ 01280 _argvec[7] = (unsigned long)(arg7); \ 01281 _argvec[8] = (unsigned long)(arg8); \ 01282 _argvec[9] = (unsigned long)(arg9); \ 01283 __asm__ volatile( \ 01284 "subq $128,%%rsp\n\t" \ 01285 "pushq 72(%%rax)\n\t" \ 01286 "pushq 64(%%rax)\n\t" \ 01287 "pushq 56(%%rax)\n\t" \ 01288 "movq 48(%%rax), %%r9\n\t" \ 01289 "movq 40(%%rax), %%r8\n\t" \ 01290 "movq 32(%%rax), %%rcx\n\t" \ 01291 "movq 24(%%rax), %%rdx\n\t" \ 01292 "movq 16(%%rax), %%rsi\n\t" \ 01293 "movq 8(%%rax), %%rdi\n\t" \ 01294 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 01295 VALGRIND_CALL_NOREDIR_RAX \ 01296 "addq $24, %%rsp\n" \ 01297 "addq $128,%%rsp\n\t" \ 01298 : /*out*/ "=a" (_res) \ 01299 : /*in*/ "a" (&_argvec[0]) \ 01300 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01301 ); \ 01302 lval = (__typeof__(lval)) _res; \ 01303 } while (0) 01304 01305 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 01306 arg7,arg8,arg9,arg10) \ 01307 do { \ 01308 volatile OrigFn _orig = (orig); \ 01309 volatile unsigned long _argvec[11]; \ 01310 volatile unsigned long _res; \ 01311 _argvec[0] = (unsigned long)_orig.nraddr; \ 01312 _argvec[1] = (unsigned long)(arg1); \ 01313 _argvec[2] = (unsigned long)(arg2); \ 01314 _argvec[3] = (unsigned long)(arg3); \ 01315 _argvec[4] = (unsigned long)(arg4); \ 01316 _argvec[5] = (unsigned long)(arg5); \ 01317 _argvec[6] = (unsigned long)(arg6); \ 01318 _argvec[7] = (unsigned long)(arg7); \ 01319 _argvec[8] = (unsigned long)(arg8); \ 01320 _argvec[9] = (unsigned long)(arg9); \ 01321 _argvec[10] = (unsigned long)(arg10); \ 01322 __asm__ volatile( \ 01323 "subq $128,%%rsp\n\t" \ 01324 "pushq 80(%%rax)\n\t" \ 01325 "pushq 72(%%rax)\n\t" \ 01326 "pushq 64(%%rax)\n\t" \ 01327 "pushq 56(%%rax)\n\t" \ 01328 "movq 48(%%rax), %%r9\n\t" \ 01329 "movq 40(%%rax), %%r8\n\t" \ 01330 "movq 32(%%rax), %%rcx\n\t" \ 01331 "movq 24(%%rax), %%rdx\n\t" \ 01332 "movq 16(%%rax), %%rsi\n\t" \ 01333 "movq 8(%%rax), %%rdi\n\t" \ 01334 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 01335 VALGRIND_CALL_NOREDIR_RAX \ 01336 "addq $32, %%rsp\n" \ 01337 "addq $128,%%rsp\n\t" \ 01338 : /*out*/ "=a" (_res) \ 01339 : /*in*/ "a" (&_argvec[0]) \ 01340 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01341 ); \ 01342 lval = (__typeof__(lval)) _res; \ 01343 } while (0) 01344 01345 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 01346 arg7,arg8,arg9,arg10,arg11) \ 01347 do { \ 01348 volatile OrigFn _orig = (orig); \ 01349 volatile unsigned long _argvec[12]; \ 01350 volatile unsigned long _res; \ 01351 _argvec[0] = (unsigned long)_orig.nraddr; \ 01352 _argvec[1] = (unsigned long)(arg1); \ 01353 _argvec[2] = (unsigned long)(arg2); \ 01354 _argvec[3] = (unsigned long)(arg3); \ 01355 _argvec[4] = (unsigned long)(arg4); \ 01356 _argvec[5] = (unsigned long)(arg5); \ 01357 _argvec[6] = (unsigned long)(arg6); \ 01358 _argvec[7] = (unsigned long)(arg7); \ 01359 _argvec[8] = (unsigned long)(arg8); \ 01360 _argvec[9] = (unsigned long)(arg9); \ 01361 _argvec[10] = (unsigned long)(arg10); \ 01362 _argvec[11] = (unsigned long)(arg11); \ 01363 __asm__ volatile( \ 01364 "subq $128,%%rsp\n\t" \ 01365 "pushq 88(%%rax)\n\t" \ 01366 "pushq 80(%%rax)\n\t" \ 01367 "pushq 72(%%rax)\n\t" \ 01368 "pushq 64(%%rax)\n\t" \ 01369 "pushq 56(%%rax)\n\t" \ 01370 "movq 48(%%rax), %%r9\n\t" \ 01371 "movq 40(%%rax), %%r8\n\t" \ 01372 "movq 32(%%rax), %%rcx\n\t" \ 01373 "movq 24(%%rax), %%rdx\n\t" \ 01374 "movq 16(%%rax), %%rsi\n\t" \ 01375 "movq 8(%%rax), %%rdi\n\t" \ 01376 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 01377 VALGRIND_CALL_NOREDIR_RAX \ 01378 "addq $40, %%rsp\n" \ 01379 "addq $128,%%rsp\n\t" \ 01380 : /*out*/ "=a" (_res) \ 01381 : /*in*/ "a" (&_argvec[0]) \ 01382 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01383 ); \ 01384 lval = (__typeof__(lval)) _res; \ 01385 } while (0) 01386 01387 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 01388 arg7,arg8,arg9,arg10,arg11,arg12) \ 01389 do { \ 01390 volatile OrigFn _orig = (orig); \ 01391 volatile unsigned long _argvec[13]; \ 01392 volatile unsigned long _res; \ 01393 _argvec[0] = (unsigned long)_orig.nraddr; \ 01394 _argvec[1] = (unsigned long)(arg1); \ 01395 _argvec[2] = (unsigned long)(arg2); \ 01396 _argvec[3] = (unsigned long)(arg3); \ 01397 _argvec[4] = (unsigned long)(arg4); \ 01398 _argvec[5] = (unsigned long)(arg5); \ 01399 _argvec[6] = (unsigned long)(arg6); \ 01400 _argvec[7] = (unsigned long)(arg7); \ 01401 _argvec[8] = (unsigned long)(arg8); \ 01402 _argvec[9] = (unsigned long)(arg9); \ 01403 _argvec[10] = (unsigned long)(arg10); \ 01404 _argvec[11] = (unsigned long)(arg11); \ 01405 _argvec[12] = (unsigned long)(arg12); \ 01406 __asm__ volatile( \ 01407 "subq $128,%%rsp\n\t" \ 01408 "pushq 96(%%rax)\n\t" \ 01409 "pushq 88(%%rax)\n\t" \ 01410 "pushq 80(%%rax)\n\t" \ 01411 "pushq 72(%%rax)\n\t" \ 01412 "pushq 64(%%rax)\n\t" \ 01413 "pushq 56(%%rax)\n\t" \ 01414 "movq 48(%%rax), %%r9\n\t" \ 01415 "movq 40(%%rax), %%r8\n\t" \ 01416 "movq 32(%%rax), %%rcx\n\t" \ 01417 "movq 24(%%rax), %%rdx\n\t" \ 01418 "movq 16(%%rax), %%rsi\n\t" \ 01419 "movq 8(%%rax), %%rdi\n\t" \ 01420 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 01421 VALGRIND_CALL_NOREDIR_RAX \ 01422 "addq $48, %%rsp\n" \ 01423 "addq $128,%%rsp\n\t" \ 01424 : /*out*/ "=a" (_res) \ 01425 : /*in*/ "a" (&_argvec[0]) \ 01426 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01427 ); \ 01428 lval = (__typeof__(lval)) _res; \ 01429 } while (0) 01430 01431 #endif /* PLAT_amd64_linux */ 01432 01433 /* ------------------------ ppc32-linux ------------------------ */ 01434 01435 #if defined(PLAT_ppc32_linux) 01436 01437 /* This is useful for finding out about the on-stack stuff: 01438 01439 extern int f9 ( int,int,int,int,int,int,int,int,int ); 01440 extern int f10 ( int,int,int,int,int,int,int,int,int,int ); 01441 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int ); 01442 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int ); 01443 01444 int g9 ( void ) { 01445 return f9(11,22,33,44,55,66,77,88,99); 01446 } 01447 int g10 ( void ) { 01448 return f10(11,22,33,44,55,66,77,88,99,110); 01449 } 01450 int g11 ( void ) { 01451 return f11(11,22,33,44,55,66,77,88,99,110,121); 01452 } 01453 int g12 ( void ) { 01454 return f12(11,22,33,44,55,66,77,88,99,110,121,132); 01455 } 01456 */ 01457 01458 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ 01459 01460 /* These regs are trashed by the hidden call. */ 01461 #define __CALLER_SAVED_REGS \ 01462 "lr", "ctr", "xer", \ 01463 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ 01464 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ 01465 "r11", "r12", "r13" 01466 01467 /* These CALL_FN_ macros assume that on ppc32-linux, 01468 sizeof(unsigned long) == 4. */ 01469 01470 #define CALL_FN_W_v(lval, orig) \ 01471 do { \ 01472 volatile OrigFn _orig = (orig); \ 01473 volatile unsigned long _argvec[1]; \ 01474 volatile unsigned long _res; \ 01475 _argvec[0] = (unsigned long)_orig.nraddr; \ 01476 __asm__ volatile( \ 01477 "mr 11,%1\n\t" \ 01478 "lwz 11,0(11)\n\t" /* target->r11 */ \ 01479 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 01480 "mr %0,3" \ 01481 : /*out*/ "=r" (_res) \ 01482 : /*in*/ "r" (&_argvec[0]) \ 01483 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01484 ); \ 01485 lval = (__typeof__(lval)) _res; \ 01486 } while (0) 01487 01488 #define CALL_FN_W_W(lval, orig, arg1) \ 01489 do { \ 01490 volatile OrigFn _orig = (orig); \ 01491 volatile unsigned long _argvec[2]; \ 01492 volatile unsigned long _res; \ 01493 _argvec[0] = (unsigned long)_orig.nraddr; \ 01494 _argvec[1] = (unsigned long)arg1; \ 01495 __asm__ volatile( \ 01496 "mr 11,%1\n\t" \ 01497 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 01498 "lwz 11,0(11)\n\t" /* target->r11 */ \ 01499 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 01500 "mr %0,3" \ 01501 : /*out*/ "=r" (_res) \ 01502 : /*in*/ "r" (&_argvec[0]) \ 01503 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01504 ); \ 01505 lval = (__typeof__(lval)) _res; \ 01506 } while (0) 01507 01508 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 01509 do { \ 01510 volatile OrigFn _orig = (orig); \ 01511 volatile unsigned long _argvec[3]; \ 01512 volatile unsigned long _res; \ 01513 _argvec[0] = (unsigned long)_orig.nraddr; \ 01514 _argvec[1] = (unsigned long)arg1; \ 01515 _argvec[2] = (unsigned long)arg2; \ 01516 __asm__ volatile( \ 01517 "mr 11,%1\n\t" \ 01518 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 01519 "lwz 4,8(11)\n\t" \ 01520 "lwz 11,0(11)\n\t" /* target->r11 */ \ 01521 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 01522 "mr %0,3" \ 01523 : /*out*/ "=r" (_res) \ 01524 : /*in*/ "r" (&_argvec[0]) \ 01525 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01526 ); \ 01527 lval = (__typeof__(lval)) _res; \ 01528 } while (0) 01529 01530 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 01531 do { \ 01532 volatile OrigFn _orig = (orig); \ 01533 volatile unsigned long _argvec[4]; \ 01534 volatile unsigned long _res; \ 01535 _argvec[0] = (unsigned long)_orig.nraddr; \ 01536 _argvec[1] = (unsigned long)arg1; \ 01537 _argvec[2] = (unsigned long)arg2; \ 01538 _argvec[3] = (unsigned long)arg3; \ 01539 __asm__ volatile( \ 01540 "mr 11,%1\n\t" \ 01541 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 01542 "lwz 4,8(11)\n\t" \ 01543 "lwz 5,12(11)\n\t" \ 01544 "lwz 11,0(11)\n\t" /* target->r11 */ \ 01545 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 01546 "mr %0,3" \ 01547 : /*out*/ "=r" (_res) \ 01548 : /*in*/ "r" (&_argvec[0]) \ 01549 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01550 ); \ 01551 lval = (__typeof__(lval)) _res; \ 01552 } while (0) 01553 01554 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 01555 do { \ 01556 volatile OrigFn _orig = (orig); \ 01557 volatile unsigned long _argvec[5]; \ 01558 volatile unsigned long _res; \ 01559 _argvec[0] = (unsigned long)_orig.nraddr; \ 01560 _argvec[1] = (unsigned long)arg1; \ 01561 _argvec[2] = (unsigned long)arg2; \ 01562 _argvec[3] = (unsigned long)arg3; \ 01563 _argvec[4] = (unsigned long)arg4; \ 01564 __asm__ volatile( \ 01565 "mr 11,%1\n\t" \ 01566 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 01567 "lwz 4,8(11)\n\t" \ 01568 "lwz 5,12(11)\n\t" \ 01569 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 01570 "lwz 11,0(11)\n\t" /* target->r11 */ \ 01571 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 01572 "mr %0,3" \ 01573 : /*out*/ "=r" (_res) \ 01574 : /*in*/ "r" (&_argvec[0]) \ 01575 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01576 ); \ 01577 lval = (__typeof__(lval)) _res; \ 01578 } while (0) 01579 01580 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 01581 do { \ 01582 volatile OrigFn _orig = (orig); \ 01583 volatile unsigned long _argvec[6]; \ 01584 volatile unsigned long _res; \ 01585 _argvec[0] = (unsigned long)_orig.nraddr; \ 01586 _argvec[1] = (unsigned long)arg1; \ 01587 _argvec[2] = (unsigned long)arg2; \ 01588 _argvec[3] = (unsigned long)arg3; \ 01589 _argvec[4] = (unsigned long)arg4; \ 01590 _argvec[5] = (unsigned long)arg5; \ 01591 __asm__ volatile( \ 01592 "mr 11,%1\n\t" \ 01593 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 01594 "lwz 4,8(11)\n\t" \ 01595 "lwz 5,12(11)\n\t" \ 01596 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 01597 "lwz 7,20(11)\n\t" \ 01598 "lwz 11,0(11)\n\t" /* target->r11 */ \ 01599 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 01600 "mr %0,3" \ 01601 : /*out*/ "=r" (_res) \ 01602 : /*in*/ "r" (&_argvec[0]) \ 01603 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01604 ); \ 01605 lval = (__typeof__(lval)) _res; \ 01606 } while (0) 01607 01608 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 01609 do { \ 01610 volatile OrigFn _orig = (orig); \ 01611 volatile unsigned long _argvec[7]; \ 01612 volatile unsigned long _res; \ 01613 _argvec[0] = (unsigned long)_orig.nraddr; \ 01614 _argvec[1] = (unsigned long)arg1; \ 01615 _argvec[2] = (unsigned long)arg2; \ 01616 _argvec[3] = (unsigned long)arg3; \ 01617 _argvec[4] = (unsigned long)arg4; \ 01618 _argvec[5] = (unsigned long)arg5; \ 01619 _argvec[6] = (unsigned long)arg6; \ 01620 __asm__ volatile( \ 01621 "mr 11,%1\n\t" \ 01622 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 01623 "lwz 4,8(11)\n\t" \ 01624 "lwz 5,12(11)\n\t" \ 01625 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 01626 "lwz 7,20(11)\n\t" \ 01627 "lwz 8,24(11)\n\t" \ 01628 "lwz 11,0(11)\n\t" /* target->r11 */ \ 01629 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 01630 "mr %0,3" \ 01631 : /*out*/ "=r" (_res) \ 01632 : /*in*/ "r" (&_argvec[0]) \ 01633 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01634 ); \ 01635 lval = (__typeof__(lval)) _res; \ 01636 } while (0) 01637 01638 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 01639 arg7) \ 01640 do { \ 01641 volatile OrigFn _orig = (orig); \ 01642 volatile unsigned long _argvec[8]; \ 01643 volatile unsigned long _res; \ 01644 _argvec[0] = (unsigned long)_orig.nraddr; \ 01645 _argvec[1] = (unsigned long)arg1; \ 01646 _argvec[2] = (unsigned long)arg2; \ 01647 _argvec[3] = (unsigned long)arg3; \ 01648 _argvec[4] = (unsigned long)arg4; \ 01649 _argvec[5] = (unsigned long)arg5; \ 01650 _argvec[6] = (unsigned long)arg6; \ 01651 _argvec[7] = (unsigned long)arg7; \ 01652 __asm__ volatile( \ 01653 "mr 11,%1\n\t" \ 01654 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 01655 "lwz 4,8(11)\n\t" \ 01656 "lwz 5,12(11)\n\t" \ 01657 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 01658 "lwz 7,20(11)\n\t" \ 01659 "lwz 8,24(11)\n\t" \ 01660 "lwz 9,28(11)\n\t" \ 01661 "lwz 11,0(11)\n\t" /* target->r11 */ \ 01662 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 01663 "mr %0,3" \ 01664 : /*out*/ "=r" (_res) \ 01665 : /*in*/ "r" (&_argvec[0]) \ 01666 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01667 ); \ 01668 lval = (__typeof__(lval)) _res; \ 01669 } while (0) 01670 01671 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 01672 arg7,arg8) \ 01673 do { \ 01674 volatile OrigFn _orig = (orig); \ 01675 volatile unsigned long _argvec[9]; \ 01676 volatile unsigned long _res; \ 01677 _argvec[0] = (unsigned long)_orig.nraddr; \ 01678 _argvec[1] = (unsigned long)arg1; \ 01679 _argvec[2] = (unsigned long)arg2; \ 01680 _argvec[3] = (unsigned long)arg3; \ 01681 _argvec[4] = (unsigned long)arg4; \ 01682 _argvec[5] = (unsigned long)arg5; \ 01683 _argvec[6] = (unsigned long)arg6; \ 01684 _argvec[7] = (unsigned long)arg7; \ 01685 _argvec[8] = (unsigned long)arg8; \ 01686 __asm__ volatile( \ 01687 "mr 11,%1\n\t" \ 01688 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 01689 "lwz 4,8(11)\n\t" \ 01690 "lwz 5,12(11)\n\t" \ 01691 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 01692 "lwz 7,20(11)\n\t" \ 01693 "lwz 8,24(11)\n\t" \ 01694 "lwz 9,28(11)\n\t" \ 01695 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 01696 "lwz 11,0(11)\n\t" /* target->r11 */ \ 01697 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 01698 "mr %0,3" \ 01699 : /*out*/ "=r" (_res) \ 01700 : /*in*/ "r" (&_argvec[0]) \ 01701 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01702 ); \ 01703 lval = (__typeof__(lval)) _res; \ 01704 } while (0) 01705 01706 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 01707 arg7,arg8,arg9) \ 01708 do { \ 01709 volatile OrigFn _orig = (orig); \ 01710 volatile unsigned long _argvec[10]; \ 01711 volatile unsigned long _res; \ 01712 _argvec[0] = (unsigned long)_orig.nraddr; \ 01713 _argvec[1] = (unsigned long)arg1; \ 01714 _argvec[2] = (unsigned long)arg2; \ 01715 _argvec[3] = (unsigned long)arg3; \ 01716 _argvec[4] = (unsigned long)arg4; \ 01717 _argvec[5] = (unsigned long)arg5; \ 01718 _argvec[6] = (unsigned long)arg6; \ 01719 _argvec[7] = (unsigned long)arg7; \ 01720 _argvec[8] = (unsigned long)arg8; \ 01721 _argvec[9] = (unsigned long)arg9; \ 01722 __asm__ volatile( \ 01723 "mr 11,%1\n\t" \ 01724 "addi 1,1,-16\n\t" \ 01725 /* arg9 */ \ 01726 "lwz 3,36(11)\n\t" \ 01727 "stw 3,8(1)\n\t" \ 01728 /* args1-8 */ \ 01729 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 01730 "lwz 4,8(11)\n\t" \ 01731 "lwz 5,12(11)\n\t" \ 01732 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 01733 "lwz 7,20(11)\n\t" \ 01734 "lwz 8,24(11)\n\t" \ 01735 "lwz 9,28(11)\n\t" \ 01736 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 01737 "lwz 11,0(11)\n\t" /* target->r11 */ \ 01738 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 01739 "addi 1,1,16\n\t" \ 01740 "mr %0,3" \ 01741 : /*out*/ "=r" (_res) \ 01742 : /*in*/ "r" (&_argvec[0]) \ 01743 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01744 ); \ 01745 lval = (__typeof__(lval)) _res; \ 01746 } while (0) 01747 01748 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 01749 arg7,arg8,arg9,arg10) \ 01750 do { \ 01751 volatile OrigFn _orig = (orig); \ 01752 volatile unsigned long _argvec[11]; \ 01753 volatile unsigned long _res; \ 01754 _argvec[0] = (unsigned long)_orig.nraddr; \ 01755 _argvec[1] = (unsigned long)arg1; \ 01756 _argvec[2] = (unsigned long)arg2; \ 01757 _argvec[3] = (unsigned long)arg3; \ 01758 _argvec[4] = (unsigned long)arg4; \ 01759 _argvec[5] = (unsigned long)arg5; \ 01760 _argvec[6] = (unsigned long)arg6; \ 01761 _argvec[7] = (unsigned long)arg7; \ 01762 _argvec[8] = (unsigned long)arg8; \ 01763 _argvec[9] = (unsigned long)arg9; \ 01764 _argvec[10] = (unsigned long)arg10; \ 01765 __asm__ volatile( \ 01766 "mr 11,%1\n\t" \ 01767 "addi 1,1,-16\n\t" \ 01768 /* arg10 */ \ 01769 "lwz 3,40(11)\n\t" \ 01770 "stw 3,12(1)\n\t" \ 01771 /* arg9 */ \ 01772 "lwz 3,36(11)\n\t" \ 01773 "stw 3,8(1)\n\t" \ 01774 /* args1-8 */ \ 01775 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 01776 "lwz 4,8(11)\n\t" \ 01777 "lwz 5,12(11)\n\t" \ 01778 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 01779 "lwz 7,20(11)\n\t" \ 01780 "lwz 8,24(11)\n\t" \ 01781 "lwz 9,28(11)\n\t" \ 01782 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 01783 "lwz 11,0(11)\n\t" /* target->r11 */ \ 01784 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 01785 "addi 1,1,16\n\t" \ 01786 "mr %0,3" \ 01787 : /*out*/ "=r" (_res) \ 01788 : /*in*/ "r" (&_argvec[0]) \ 01789 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01790 ); \ 01791 lval = (__typeof__(lval)) _res; \ 01792 } while (0) 01793 01794 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 01795 arg7,arg8,arg9,arg10,arg11) \ 01796 do { \ 01797 volatile OrigFn _orig = (orig); \ 01798 volatile unsigned long _argvec[12]; \ 01799 volatile unsigned long _res; \ 01800 _argvec[0] = (unsigned long)_orig.nraddr; \ 01801 _argvec[1] = (unsigned long)arg1; \ 01802 _argvec[2] = (unsigned long)arg2; \ 01803 _argvec[3] = (unsigned long)arg3; \ 01804 _argvec[4] = (unsigned long)arg4; \ 01805 _argvec[5] = (unsigned long)arg5; \ 01806 _argvec[6] = (unsigned long)arg6; \ 01807 _argvec[7] = (unsigned long)arg7; \ 01808 _argvec[8] = (unsigned long)arg8; \ 01809 _argvec[9] = (unsigned long)arg9; \ 01810 _argvec[10] = (unsigned long)arg10; \ 01811 _argvec[11] = (unsigned long)arg11; \ 01812 __asm__ volatile( \ 01813 "mr 11,%1\n\t" \ 01814 "addi 1,1,-32\n\t" \ 01815 /* arg11 */ \ 01816 "lwz 3,44(11)\n\t" \ 01817 "stw 3,16(1)\n\t" \ 01818 /* arg10 */ \ 01819 "lwz 3,40(11)\n\t" \ 01820 "stw 3,12(1)\n\t" \ 01821 /* arg9 */ \ 01822 "lwz 3,36(11)\n\t" \ 01823 "stw 3,8(1)\n\t" \ 01824 /* args1-8 */ \ 01825 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 01826 "lwz 4,8(11)\n\t" \ 01827 "lwz 5,12(11)\n\t" \ 01828 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 01829 "lwz 7,20(11)\n\t" \ 01830 "lwz 8,24(11)\n\t" \ 01831 "lwz 9,28(11)\n\t" \ 01832 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 01833 "lwz 11,0(11)\n\t" /* target->r11 */ \ 01834 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 01835 "addi 1,1,32\n\t" \ 01836 "mr %0,3" \ 01837 : /*out*/ "=r" (_res) \ 01838 : /*in*/ "r" (&_argvec[0]) \ 01839 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01840 ); \ 01841 lval = (__typeof__(lval)) _res; \ 01842 } while (0) 01843 01844 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 01845 arg7,arg8,arg9,arg10,arg11,arg12) \ 01846 do { \ 01847 volatile OrigFn _orig = (orig); \ 01848 volatile unsigned long _argvec[13]; \ 01849 volatile unsigned long _res; \ 01850 _argvec[0] = (unsigned long)_orig.nraddr; \ 01851 _argvec[1] = (unsigned long)arg1; \ 01852 _argvec[2] = (unsigned long)arg2; \ 01853 _argvec[3] = (unsigned long)arg3; \ 01854 _argvec[4] = (unsigned long)arg4; \ 01855 _argvec[5] = (unsigned long)arg5; \ 01856 _argvec[6] = (unsigned long)arg6; \ 01857 _argvec[7] = (unsigned long)arg7; \ 01858 _argvec[8] = (unsigned long)arg8; \ 01859 _argvec[9] = (unsigned long)arg9; \ 01860 _argvec[10] = (unsigned long)arg10; \ 01861 _argvec[11] = (unsigned long)arg11; \ 01862 _argvec[12] = (unsigned long)arg12; \ 01863 __asm__ volatile( \ 01864 "mr 11,%1\n\t" \ 01865 "addi 1,1,-32\n\t" \ 01866 /* arg12 */ \ 01867 "lwz 3,48(11)\n\t" \ 01868 "stw 3,20(1)\n\t" \ 01869 /* arg11 */ \ 01870 "lwz 3,44(11)\n\t" \ 01871 "stw 3,16(1)\n\t" \ 01872 /* arg10 */ \ 01873 "lwz 3,40(11)\n\t" \ 01874 "stw 3,12(1)\n\t" \ 01875 /* arg9 */ \ 01876 "lwz 3,36(11)\n\t" \ 01877 "stw 3,8(1)\n\t" \ 01878 /* args1-8 */ \ 01879 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 01880 "lwz 4,8(11)\n\t" \ 01881 "lwz 5,12(11)\n\t" \ 01882 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 01883 "lwz 7,20(11)\n\t" \ 01884 "lwz 8,24(11)\n\t" \ 01885 "lwz 9,28(11)\n\t" \ 01886 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 01887 "lwz 11,0(11)\n\t" /* target->r11 */ \ 01888 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 01889 "addi 1,1,32\n\t" \ 01890 "mr %0,3" \ 01891 : /*out*/ "=r" (_res) \ 01892 : /*in*/ "r" (&_argvec[0]) \ 01893 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01894 ); \ 01895 lval = (__typeof__(lval)) _res; \ 01896 } while (0) 01897 01898 #endif /* PLAT_ppc32_linux */ 01899 01900 /* ------------------------ ppc64-linux ------------------------ */ 01901 01902 #if defined(PLAT_ppc64_linux) 01903 01904 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ 01905 01906 /* These regs are trashed by the hidden call. */ 01907 #define __CALLER_SAVED_REGS \ 01908 "lr", "ctr", "xer", \ 01909 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ 01910 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ 01911 "r11", "r12", "r13" 01912 01913 /* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned 01914 long) == 8. */ 01915 01916 #define CALL_FN_W_v(lval, orig) \ 01917 do { \ 01918 volatile OrigFn _orig = (orig); \ 01919 volatile unsigned long _argvec[3+0]; \ 01920 volatile unsigned long _res; \ 01921 /* _argvec[0] holds current r2 across the call */ \ 01922 _argvec[1] = (unsigned long)_orig.r2; \ 01923 _argvec[2] = (unsigned long)_orig.nraddr; \ 01924 __asm__ volatile( \ 01925 "mr 11,%1\n\t" \ 01926 "std 2,-16(11)\n\t" /* save tocptr */ \ 01927 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 01928 "ld 11, 0(11)\n\t" /* target->r11 */ \ 01929 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 01930 "mr 11,%1\n\t" \ 01931 "mr %0,3\n\t" \ 01932 "ld 2,-16(11)" /* restore tocptr */ \ 01933 : /*out*/ "=r" (_res) \ 01934 : /*in*/ "r" (&_argvec[2]) \ 01935 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01936 ); \ 01937 lval = (__typeof__(lval)) _res; \ 01938 } while (0) 01939 01940 #define CALL_FN_W_W(lval, orig, arg1) \ 01941 do { \ 01942 volatile OrigFn _orig = (orig); \ 01943 volatile unsigned long _argvec[3+1]; \ 01944 volatile unsigned long _res; \ 01945 /* _argvec[0] holds current r2 across the call */ \ 01946 _argvec[1] = (unsigned long)_orig.r2; \ 01947 _argvec[2] = (unsigned long)_orig.nraddr; \ 01948 _argvec[2+1] = (unsigned long)arg1; \ 01949 __asm__ volatile( \ 01950 "mr 11,%1\n\t" \ 01951 "std 2,-16(11)\n\t" /* save tocptr */ \ 01952 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 01953 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 01954 "ld 11, 0(11)\n\t" /* target->r11 */ \ 01955 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 01956 "mr 11,%1\n\t" \ 01957 "mr %0,3\n\t" \ 01958 "ld 2,-16(11)" /* restore tocptr */ \ 01959 : /*out*/ "=r" (_res) \ 01960 : /*in*/ "r" (&_argvec[2]) \ 01961 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01962 ); \ 01963 lval = (__typeof__(lval)) _res; \ 01964 } while (0) 01965 01966 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 01967 do { \ 01968 volatile OrigFn _orig = (orig); \ 01969 volatile unsigned long _argvec[3+2]; \ 01970 volatile unsigned long _res; \ 01971 /* _argvec[0] holds current r2 across the call */ \ 01972 _argvec[1] = (unsigned long)_orig.r2; \ 01973 _argvec[2] = (unsigned long)_orig.nraddr; \ 01974 _argvec[2+1] = (unsigned long)arg1; \ 01975 _argvec[2+2] = (unsigned long)arg2; \ 01976 __asm__ volatile( \ 01977 "mr 11,%1\n\t" \ 01978 "std 2,-16(11)\n\t" /* save tocptr */ \ 01979 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 01980 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 01981 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 01982 "ld 11, 0(11)\n\t" /* target->r11 */ \ 01983 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 01984 "mr 11,%1\n\t" \ 01985 "mr %0,3\n\t" \ 01986 "ld 2,-16(11)" /* restore tocptr */ \ 01987 : /*out*/ "=r" (_res) \ 01988 : /*in*/ "r" (&_argvec[2]) \ 01989 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 01990 ); \ 01991 lval = (__typeof__(lval)) _res; \ 01992 } while (0) 01993 01994 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 01995 do { \ 01996 volatile OrigFn _orig = (orig); \ 01997 volatile unsigned long _argvec[3+3]; \ 01998 volatile unsigned long _res; \ 01999 /* _argvec[0] holds current r2 across the call */ \ 02000 _argvec[1] = (unsigned long)_orig.r2; \ 02001 _argvec[2] = (unsigned long)_orig.nraddr; \ 02002 _argvec[2+1] = (unsigned long)arg1; \ 02003 _argvec[2+2] = (unsigned long)arg2; \ 02004 _argvec[2+3] = (unsigned long)arg3; \ 02005 __asm__ volatile( \ 02006 "mr 11,%1\n\t" \ 02007 "std 2,-16(11)\n\t" /* save tocptr */ \ 02008 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 02009 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 02010 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 02011 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 02012 "ld 11, 0(11)\n\t" /* target->r11 */ \ 02013 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02014 "mr 11,%1\n\t" \ 02015 "mr %0,3\n\t" \ 02016 "ld 2,-16(11)" /* restore tocptr */ \ 02017 : /*out*/ "=r" (_res) \ 02018 : /*in*/ "r" (&_argvec[2]) \ 02019 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02020 ); \ 02021 lval = (__typeof__(lval)) _res; \ 02022 } while (0) 02023 02024 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 02025 do { \ 02026 volatile OrigFn _orig = (orig); \ 02027 volatile unsigned long _argvec[3+4]; \ 02028 volatile unsigned long _res; \ 02029 /* _argvec[0] holds current r2 across the call */ \ 02030 _argvec[1] = (unsigned long)_orig.r2; \ 02031 _argvec[2] = (unsigned long)_orig.nraddr; \ 02032 _argvec[2+1] = (unsigned long)arg1; \ 02033 _argvec[2+2] = (unsigned long)arg2; \ 02034 _argvec[2+3] = (unsigned long)arg3; \ 02035 _argvec[2+4] = (unsigned long)arg4; \ 02036 __asm__ volatile( \ 02037 "mr 11,%1\n\t" \ 02038 "std 2,-16(11)\n\t" /* save tocptr */ \ 02039 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 02040 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 02041 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 02042 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 02043 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 02044 "ld 11, 0(11)\n\t" /* target->r11 */ \ 02045 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02046 "mr 11,%1\n\t" \ 02047 "mr %0,3\n\t" \ 02048 "ld 2,-16(11)" /* restore tocptr */ \ 02049 : /*out*/ "=r" (_res) \ 02050 : /*in*/ "r" (&_argvec[2]) \ 02051 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02052 ); \ 02053 lval = (__typeof__(lval)) _res; \ 02054 } while (0) 02055 02056 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 02057 do { \ 02058 volatile OrigFn _orig = (orig); \ 02059 volatile unsigned long _argvec[3+5]; \ 02060 volatile unsigned long _res; \ 02061 /* _argvec[0] holds current r2 across the call */ \ 02062 _argvec[1] = (unsigned long)_orig.r2; \ 02063 _argvec[2] = (unsigned long)_orig.nraddr; \ 02064 _argvec[2+1] = (unsigned long)arg1; \ 02065 _argvec[2+2] = (unsigned long)arg2; \ 02066 _argvec[2+3] = (unsigned long)arg3; \ 02067 _argvec[2+4] = (unsigned long)arg4; \ 02068 _argvec[2+5] = (unsigned long)arg5; \ 02069 __asm__ volatile( \ 02070 "mr 11,%1\n\t" \ 02071 "std 2,-16(11)\n\t" /* save tocptr */ \ 02072 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 02073 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 02074 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 02075 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 02076 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 02077 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 02078 "ld 11, 0(11)\n\t" /* target->r11 */ \ 02079 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02080 "mr 11,%1\n\t" \ 02081 "mr %0,3\n\t" \ 02082 "ld 2,-16(11)" /* restore tocptr */ \ 02083 : /*out*/ "=r" (_res) \ 02084 : /*in*/ "r" (&_argvec[2]) \ 02085 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02086 ); \ 02087 lval = (__typeof__(lval)) _res; \ 02088 } while (0) 02089 02090 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 02091 do { \ 02092 volatile OrigFn _orig = (orig); \ 02093 volatile unsigned long _argvec[3+6]; \ 02094 volatile unsigned long _res; \ 02095 /* _argvec[0] holds current r2 across the call */ \ 02096 _argvec[1] = (unsigned long)_orig.r2; \ 02097 _argvec[2] = (unsigned long)_orig.nraddr; \ 02098 _argvec[2+1] = (unsigned long)arg1; \ 02099 _argvec[2+2] = (unsigned long)arg2; \ 02100 _argvec[2+3] = (unsigned long)arg3; \ 02101 _argvec[2+4] = (unsigned long)arg4; \ 02102 _argvec[2+5] = (unsigned long)arg5; \ 02103 _argvec[2+6] = (unsigned long)arg6; \ 02104 __asm__ volatile( \ 02105 "mr 11,%1\n\t" \ 02106 "std 2,-16(11)\n\t" /* save tocptr */ \ 02107 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 02108 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 02109 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 02110 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 02111 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 02112 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 02113 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 02114 "ld 11, 0(11)\n\t" /* target->r11 */ \ 02115 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02116 "mr 11,%1\n\t" \ 02117 "mr %0,3\n\t" \ 02118 "ld 2,-16(11)" /* restore tocptr */ \ 02119 : /*out*/ "=r" (_res) \ 02120 : /*in*/ "r" (&_argvec[2]) \ 02121 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02122 ); \ 02123 lval = (__typeof__(lval)) _res; \ 02124 } while (0) 02125 02126 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 02127 arg7) \ 02128 do { \ 02129 volatile OrigFn _orig = (orig); \ 02130 volatile unsigned long _argvec[3+7]; \ 02131 volatile unsigned long _res; \ 02132 /* _argvec[0] holds current r2 across the call */ \ 02133 _argvec[1] = (unsigned long)_orig.r2; \ 02134 _argvec[2] = (unsigned long)_orig.nraddr; \ 02135 _argvec[2+1] = (unsigned long)arg1; \ 02136 _argvec[2+2] = (unsigned long)arg2; \ 02137 _argvec[2+3] = (unsigned long)arg3; \ 02138 _argvec[2+4] = (unsigned long)arg4; \ 02139 _argvec[2+5] = (unsigned long)arg5; \ 02140 _argvec[2+6] = (unsigned long)arg6; \ 02141 _argvec[2+7] = (unsigned long)arg7; \ 02142 __asm__ volatile( \ 02143 "mr 11,%1\n\t" \ 02144 "std 2,-16(11)\n\t" /* save tocptr */ \ 02145 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 02146 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 02147 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 02148 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 02149 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 02150 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 02151 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 02152 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 02153 "ld 11, 0(11)\n\t" /* target->r11 */ \ 02154 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02155 "mr 11,%1\n\t" \ 02156 "mr %0,3\n\t" \ 02157 "ld 2,-16(11)" /* restore tocptr */ \ 02158 : /*out*/ "=r" (_res) \ 02159 : /*in*/ "r" (&_argvec[2]) \ 02160 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02161 ); \ 02162 lval = (__typeof__(lval)) _res; \ 02163 } while (0) 02164 02165 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 02166 arg7,arg8) \ 02167 do { \ 02168 volatile OrigFn _orig = (orig); \ 02169 volatile unsigned long _argvec[3+8]; \ 02170 volatile unsigned long _res; \ 02171 /* _argvec[0] holds current r2 across the call */ \ 02172 _argvec[1] = (unsigned long)_orig.r2; \ 02173 _argvec[2] = (unsigned long)_orig.nraddr; \ 02174 _argvec[2+1] = (unsigned long)arg1; \ 02175 _argvec[2+2] = (unsigned long)arg2; \ 02176 _argvec[2+3] = (unsigned long)arg3; \ 02177 _argvec[2+4] = (unsigned long)arg4; \ 02178 _argvec[2+5] = (unsigned long)arg5; \ 02179 _argvec[2+6] = (unsigned long)arg6; \ 02180 _argvec[2+7] = (unsigned long)arg7; \ 02181 _argvec[2+8] = (unsigned long)arg8; \ 02182 __asm__ volatile( \ 02183 "mr 11,%1\n\t" \ 02184 "std 2,-16(11)\n\t" /* save tocptr */ \ 02185 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 02186 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 02187 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 02188 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 02189 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 02190 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 02191 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 02192 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 02193 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 02194 "ld 11, 0(11)\n\t" /* target->r11 */ \ 02195 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02196 "mr 11,%1\n\t" \ 02197 "mr %0,3\n\t" \ 02198 "ld 2,-16(11)" /* restore tocptr */ \ 02199 : /*out*/ "=r" (_res) \ 02200 : /*in*/ "r" (&_argvec[2]) \ 02201 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02202 ); \ 02203 lval = (__typeof__(lval)) _res; \ 02204 } while (0) 02205 02206 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 02207 arg7,arg8,arg9) \ 02208 do { \ 02209 volatile OrigFn _orig = (orig); \ 02210 volatile unsigned long _argvec[3+9]; \ 02211 volatile unsigned long _res; \ 02212 /* _argvec[0] holds current r2 across the call */ \ 02213 _argvec[1] = (unsigned long)_orig.r2; \ 02214 _argvec[2] = (unsigned long)_orig.nraddr; \ 02215 _argvec[2+1] = (unsigned long)arg1; \ 02216 _argvec[2+2] = (unsigned long)arg2; \ 02217 _argvec[2+3] = (unsigned long)arg3; \ 02218 _argvec[2+4] = (unsigned long)arg4; \ 02219 _argvec[2+5] = (unsigned long)arg5; \ 02220 _argvec[2+6] = (unsigned long)arg6; \ 02221 _argvec[2+7] = (unsigned long)arg7; \ 02222 _argvec[2+8] = (unsigned long)arg8; \ 02223 _argvec[2+9] = (unsigned long)arg9; \ 02224 __asm__ volatile( \ 02225 "mr 11,%1\n\t" \ 02226 "std 2,-16(11)\n\t" /* save tocptr */ \ 02227 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 02228 "addi 1,1,-128\n\t" /* expand stack frame */ \ 02229 /* arg9 */ \ 02230 "ld 3,72(11)\n\t" \ 02231 "std 3,112(1)\n\t" \ 02232 /* args1-8 */ \ 02233 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 02234 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 02235 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 02236 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 02237 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 02238 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 02239 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 02240 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 02241 "ld 11, 0(11)\n\t" /* target->r11 */ \ 02242 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02243 "mr 11,%1\n\t" \ 02244 "mr %0,3\n\t" \ 02245 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 02246 "addi 1,1,128" /* restore frame */ \ 02247 : /*out*/ "=r" (_res) \ 02248 : /*in*/ "r" (&_argvec[2]) \ 02249 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02250 ); \ 02251 lval = (__typeof__(lval)) _res; \ 02252 } while (0) 02253 02254 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 02255 arg7,arg8,arg9,arg10) \ 02256 do { \ 02257 volatile OrigFn _orig = (orig); \ 02258 volatile unsigned long _argvec[3+10]; \ 02259 volatile unsigned long _res; \ 02260 /* _argvec[0] holds current r2 across the call */ \ 02261 _argvec[1] = (unsigned long)_orig.r2; \ 02262 _argvec[2] = (unsigned long)_orig.nraddr; \ 02263 _argvec[2+1] = (unsigned long)arg1; \ 02264 _argvec[2+2] = (unsigned long)arg2; \ 02265 _argvec[2+3] = (unsigned long)arg3; \ 02266 _argvec[2+4] = (unsigned long)arg4; \ 02267 _argvec[2+5] = (unsigned long)arg5; \ 02268 _argvec[2+6] = (unsigned long)arg6; \ 02269 _argvec[2+7] = (unsigned long)arg7; \ 02270 _argvec[2+8] = (unsigned long)arg8; \ 02271 _argvec[2+9] = (unsigned long)arg9; \ 02272 _argvec[2+10] = (unsigned long)arg10; \ 02273 __asm__ volatile( \ 02274 "mr 11,%1\n\t" \ 02275 "std 2,-16(11)\n\t" /* save tocptr */ \ 02276 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 02277 "addi 1,1,-128\n\t" /* expand stack frame */ \ 02278 /* arg10 */ \ 02279 "ld 3,80(11)\n\t" \ 02280 "std 3,120(1)\n\t" \ 02281 /* arg9 */ \ 02282 "ld 3,72(11)\n\t" \ 02283 "std 3,112(1)\n\t" \ 02284 /* args1-8 */ \ 02285 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 02286 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 02287 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 02288 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 02289 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 02290 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 02291 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 02292 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 02293 "ld 11, 0(11)\n\t" /* target->r11 */ \ 02294 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02295 "mr 11,%1\n\t" \ 02296 "mr %0,3\n\t" \ 02297 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 02298 "addi 1,1,128" /* restore frame */ \ 02299 : /*out*/ "=r" (_res) \ 02300 : /*in*/ "r" (&_argvec[2]) \ 02301 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02302 ); \ 02303 lval = (__typeof__(lval)) _res; \ 02304 } while (0) 02305 02306 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 02307 arg7,arg8,arg9,arg10,arg11) \ 02308 do { \ 02309 volatile OrigFn _orig = (orig); \ 02310 volatile unsigned long _argvec[3+11]; \ 02311 volatile unsigned long _res; \ 02312 /* _argvec[0] holds current r2 across the call */ \ 02313 _argvec[1] = (unsigned long)_orig.r2; \ 02314 _argvec[2] = (unsigned long)_orig.nraddr; \ 02315 _argvec[2+1] = (unsigned long)arg1; \ 02316 _argvec[2+2] = (unsigned long)arg2; \ 02317 _argvec[2+3] = (unsigned long)arg3; \ 02318 _argvec[2+4] = (unsigned long)arg4; \ 02319 _argvec[2+5] = (unsigned long)arg5; \ 02320 _argvec[2+6] = (unsigned long)arg6; \ 02321 _argvec[2+7] = (unsigned long)arg7; \ 02322 _argvec[2+8] = (unsigned long)arg8; \ 02323 _argvec[2+9] = (unsigned long)arg9; \ 02324 _argvec[2+10] = (unsigned long)arg10; \ 02325 _argvec[2+11] = (unsigned long)arg11; \ 02326 __asm__ volatile( \ 02327 "mr 11,%1\n\t" \ 02328 "std 2,-16(11)\n\t" /* save tocptr */ \ 02329 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 02330 "addi 1,1,-144\n\t" /* expand stack frame */ \ 02331 /* arg11 */ \ 02332 "ld 3,88(11)\n\t" \ 02333 "std 3,128(1)\n\t" \ 02334 /* arg10 */ \ 02335 "ld 3,80(11)\n\t" \ 02336 "std 3,120(1)\n\t" \ 02337 /* arg9 */ \ 02338 "ld 3,72(11)\n\t" \ 02339 "std 3,112(1)\n\t" \ 02340 /* args1-8 */ \ 02341 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 02342 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 02343 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 02344 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 02345 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 02346 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 02347 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 02348 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 02349 "ld 11, 0(11)\n\t" /* target->r11 */ \ 02350 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02351 "mr 11,%1\n\t" \ 02352 "mr %0,3\n\t" \ 02353 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 02354 "addi 1,1,144" /* restore frame */ \ 02355 : /*out*/ "=r" (_res) \ 02356 : /*in*/ "r" (&_argvec[2]) \ 02357 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02358 ); \ 02359 lval = (__typeof__(lval)) _res; \ 02360 } while (0) 02361 02362 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 02363 arg7,arg8,arg9,arg10,arg11,arg12) \ 02364 do { \ 02365 volatile OrigFn _orig = (orig); \ 02366 volatile unsigned long _argvec[3+12]; \ 02367 volatile unsigned long _res; \ 02368 /* _argvec[0] holds current r2 across the call */ \ 02369 _argvec[1] = (unsigned long)_orig.r2; \ 02370 _argvec[2] = (unsigned long)_orig.nraddr; \ 02371 _argvec[2+1] = (unsigned long)arg1; \ 02372 _argvec[2+2] = (unsigned long)arg2; \ 02373 _argvec[2+3] = (unsigned long)arg3; \ 02374 _argvec[2+4] = (unsigned long)arg4; \ 02375 _argvec[2+5] = (unsigned long)arg5; \ 02376 _argvec[2+6] = (unsigned long)arg6; \ 02377 _argvec[2+7] = (unsigned long)arg7; \ 02378 _argvec[2+8] = (unsigned long)arg8; \ 02379 _argvec[2+9] = (unsigned long)arg9; \ 02380 _argvec[2+10] = (unsigned long)arg10; \ 02381 _argvec[2+11] = (unsigned long)arg11; \ 02382 _argvec[2+12] = (unsigned long)arg12; \ 02383 __asm__ volatile( \ 02384 "mr 11,%1\n\t" \ 02385 "std 2,-16(11)\n\t" /* save tocptr */ \ 02386 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 02387 "addi 1,1,-144\n\t" /* expand stack frame */ \ 02388 /* arg12 */ \ 02389 "ld 3,96(11)\n\t" \ 02390 "std 3,136(1)\n\t" \ 02391 /* arg11 */ \ 02392 "ld 3,88(11)\n\t" \ 02393 "std 3,128(1)\n\t" \ 02394 /* arg10 */ \ 02395 "ld 3,80(11)\n\t" \ 02396 "std 3,120(1)\n\t" \ 02397 /* arg9 */ \ 02398 "ld 3,72(11)\n\t" \ 02399 "std 3,112(1)\n\t" \ 02400 /* args1-8 */ \ 02401 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 02402 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 02403 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 02404 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 02405 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 02406 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 02407 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 02408 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 02409 "ld 11, 0(11)\n\t" /* target->r11 */ \ 02410 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02411 "mr 11,%1\n\t" \ 02412 "mr %0,3\n\t" \ 02413 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 02414 "addi 1,1,144" /* restore frame */ \ 02415 : /*out*/ "=r" (_res) \ 02416 : /*in*/ "r" (&_argvec[2]) \ 02417 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02418 ); \ 02419 lval = (__typeof__(lval)) _res; \ 02420 } while (0) 02421 02422 #endif /* PLAT_ppc64_linux */ 02423 02424 /* ------------------------ ppc32-aix5 ------------------------- */ 02425 02426 #if defined(PLAT_ppc32_aix5) 02427 02428 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ 02429 02430 /* These regs are trashed by the hidden call. */ 02431 #define __CALLER_SAVED_REGS \ 02432 "lr", "ctr", "xer", \ 02433 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ 02434 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ 02435 "r11", "r12", "r13" 02436 02437 /* Expand the stack frame, copying enough info that unwinding 02438 still works. Trashes r3. */ 02439 02440 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \ 02441 "addi 1,1,-" #_n_fr "\n\t" \ 02442 "lwz 3," #_n_fr "(1)\n\t" \ 02443 "stw 3,0(1)\n\t" 02444 02445 #define VG_CONTRACT_FRAME_BY(_n_fr) \ 02446 "addi 1,1," #_n_fr "\n\t" 02447 02448 /* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned 02449 long) == 4. */ 02450 02451 #define CALL_FN_W_v(lval, orig) \ 02452 do { \ 02453 volatile OrigFn _orig = (orig); \ 02454 volatile unsigned long _argvec[3+0]; \ 02455 volatile unsigned long _res; \ 02456 /* _argvec[0] holds current r2 across the call */ \ 02457 _argvec[1] = (unsigned long)_orig.r2; \ 02458 _argvec[2] = (unsigned long)_orig.nraddr; \ 02459 __asm__ volatile( \ 02460 "mr 11,%1\n\t" \ 02461 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 02462 "stw 2,-8(11)\n\t" /* save tocptr */ \ 02463 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 02464 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 02465 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02466 "mr 11,%1\n\t" \ 02467 "mr %0,3\n\t" \ 02468 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 02469 VG_CONTRACT_FRAME_BY(512) \ 02470 : /*out*/ "=r" (_res) \ 02471 : /*in*/ "r" (&_argvec[2]) \ 02472 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02473 ); \ 02474 lval = (__typeof__(lval)) _res; \ 02475 } while (0) 02476 02477 #define CALL_FN_W_W(lval, orig, arg1) \ 02478 do { \ 02479 volatile OrigFn _orig = (orig); \ 02480 volatile unsigned long _argvec[3+1]; \ 02481 volatile unsigned long _res; \ 02482 /* _argvec[0] holds current r2 across the call */ \ 02483 _argvec[1] = (unsigned long)_orig.r2; \ 02484 _argvec[2] = (unsigned long)_orig.nraddr; \ 02485 _argvec[2+1] = (unsigned long)arg1; \ 02486 __asm__ volatile( \ 02487 "mr 11,%1\n\t" \ 02488 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 02489 "stw 2,-8(11)\n\t" /* save tocptr */ \ 02490 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 02491 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 02492 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 02493 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02494 "mr 11,%1\n\t" \ 02495 "mr %0,3\n\t" \ 02496 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 02497 VG_CONTRACT_FRAME_BY(512) \ 02498 : /*out*/ "=r" (_res) \ 02499 : /*in*/ "r" (&_argvec[2]) \ 02500 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02501 ); \ 02502 lval = (__typeof__(lval)) _res; \ 02503 } while (0) 02504 02505 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 02506 do { \ 02507 volatile OrigFn _orig = (orig); \ 02508 volatile unsigned long _argvec[3+2]; \ 02509 volatile unsigned long _res; \ 02510 /* _argvec[0] holds current r2 across the call */ \ 02511 _argvec[1] = (unsigned long)_orig.r2; \ 02512 _argvec[2] = (unsigned long)_orig.nraddr; \ 02513 _argvec[2+1] = (unsigned long)arg1; \ 02514 _argvec[2+2] = (unsigned long)arg2; \ 02515 __asm__ volatile( \ 02516 "mr 11,%1\n\t" \ 02517 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 02518 "stw 2,-8(11)\n\t" /* save tocptr */ \ 02519 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 02520 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 02521 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 02522 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 02523 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02524 "mr 11,%1\n\t" \ 02525 "mr %0,3\n\t" \ 02526 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 02527 VG_CONTRACT_FRAME_BY(512) \ 02528 : /*out*/ "=r" (_res) \ 02529 : /*in*/ "r" (&_argvec[2]) \ 02530 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02531 ); \ 02532 lval = (__typeof__(lval)) _res; \ 02533 } while (0) 02534 02535 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 02536 do { \ 02537 volatile OrigFn _orig = (orig); \ 02538 volatile unsigned long _argvec[3+3]; \ 02539 volatile unsigned long _res; \ 02540 /* _argvec[0] holds current r2 across the call */ \ 02541 _argvec[1] = (unsigned long)_orig.r2; \ 02542 _argvec[2] = (unsigned long)_orig.nraddr; \ 02543 _argvec[2+1] = (unsigned long)arg1; \ 02544 _argvec[2+2] = (unsigned long)arg2; \ 02545 _argvec[2+3] = (unsigned long)arg3; \ 02546 __asm__ volatile( \ 02547 "mr 11,%1\n\t" \ 02548 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 02549 "stw 2,-8(11)\n\t" /* save tocptr */ \ 02550 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 02551 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 02552 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 02553 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 02554 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 02555 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02556 "mr 11,%1\n\t" \ 02557 "mr %0,3\n\t" \ 02558 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 02559 VG_CONTRACT_FRAME_BY(512) \ 02560 : /*out*/ "=r" (_res) \ 02561 : /*in*/ "r" (&_argvec[2]) \ 02562 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02563 ); \ 02564 lval = (__typeof__(lval)) _res; \ 02565 } while (0) 02566 02567 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 02568 do { \ 02569 volatile OrigFn _orig = (orig); \ 02570 volatile unsigned long _argvec[3+4]; \ 02571 volatile unsigned long _res; \ 02572 /* _argvec[0] holds current r2 across the call */ \ 02573 _argvec[1] = (unsigned long)_orig.r2; \ 02574 _argvec[2] = (unsigned long)_orig.nraddr; \ 02575 _argvec[2+1] = (unsigned long)arg1; \ 02576 _argvec[2+2] = (unsigned long)arg2; \ 02577 _argvec[2+3] = (unsigned long)arg3; \ 02578 _argvec[2+4] = (unsigned long)arg4; \ 02579 __asm__ volatile( \ 02580 "mr 11,%1\n\t" \ 02581 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 02582 "stw 2,-8(11)\n\t" /* save tocptr */ \ 02583 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 02584 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 02585 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 02586 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 02587 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 02588 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 02589 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02590 "mr 11,%1\n\t" \ 02591 "mr %0,3\n\t" \ 02592 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 02593 VG_CONTRACT_FRAME_BY(512) \ 02594 : /*out*/ "=r" (_res) \ 02595 : /*in*/ "r" (&_argvec[2]) \ 02596 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02597 ); \ 02598 lval = (__typeof__(lval)) _res; \ 02599 } while (0) 02600 02601 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 02602 do { \ 02603 volatile OrigFn _orig = (orig); \ 02604 volatile unsigned long _argvec[3+5]; \ 02605 volatile unsigned long _res; \ 02606 /* _argvec[0] holds current r2 across the call */ \ 02607 _argvec[1] = (unsigned long)_orig.r2; \ 02608 _argvec[2] = (unsigned long)_orig.nraddr; \ 02609 _argvec[2+1] = (unsigned long)arg1; \ 02610 _argvec[2+2] = (unsigned long)arg2; \ 02611 _argvec[2+3] = (unsigned long)arg3; \ 02612 _argvec[2+4] = (unsigned long)arg4; \ 02613 _argvec[2+5] = (unsigned long)arg5; \ 02614 __asm__ volatile( \ 02615 "mr 11,%1\n\t" \ 02616 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 02617 "stw 2,-8(11)\n\t" /* save tocptr */ \ 02618 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 02619 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 02620 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 02621 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 02622 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 02623 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 02624 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 02625 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02626 "mr 11,%1\n\t" \ 02627 "mr %0,3\n\t" \ 02628 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 02629 VG_CONTRACT_FRAME_BY(512) \ 02630 : /*out*/ "=r" (_res) \ 02631 : /*in*/ "r" (&_argvec[2]) \ 02632 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02633 ); \ 02634 lval = (__typeof__(lval)) _res; \ 02635 } while (0) 02636 02637 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 02638 do { \ 02639 volatile OrigFn _orig = (orig); \ 02640 volatile unsigned long _argvec[3+6]; \ 02641 volatile unsigned long _res; \ 02642 /* _argvec[0] holds current r2 across the call */ \ 02643 _argvec[1] = (unsigned long)_orig.r2; \ 02644 _argvec[2] = (unsigned long)_orig.nraddr; \ 02645 _argvec[2+1] = (unsigned long)arg1; \ 02646 _argvec[2+2] = (unsigned long)arg2; \ 02647 _argvec[2+3] = (unsigned long)arg3; \ 02648 _argvec[2+4] = (unsigned long)arg4; \ 02649 _argvec[2+5] = (unsigned long)arg5; \ 02650 _argvec[2+6] = (unsigned long)arg6; \ 02651 __asm__ volatile( \ 02652 "mr 11,%1\n\t" \ 02653 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 02654 "stw 2,-8(11)\n\t" /* save tocptr */ \ 02655 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 02656 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 02657 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 02658 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 02659 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 02660 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 02661 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 02662 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 02663 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02664 "mr 11,%1\n\t" \ 02665 "mr %0,3\n\t" \ 02666 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 02667 VG_CONTRACT_FRAME_BY(512) \ 02668 : /*out*/ "=r" (_res) \ 02669 : /*in*/ "r" (&_argvec[2]) \ 02670 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02671 ); \ 02672 lval = (__typeof__(lval)) _res; \ 02673 } while (0) 02674 02675 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 02676 arg7) \ 02677 do { \ 02678 volatile OrigFn _orig = (orig); \ 02679 volatile unsigned long _argvec[3+7]; \ 02680 volatile unsigned long _res; \ 02681 /* _argvec[0] holds current r2 across the call */ \ 02682 _argvec[1] = (unsigned long)_orig.r2; \ 02683 _argvec[2] = (unsigned long)_orig.nraddr; \ 02684 _argvec[2+1] = (unsigned long)arg1; \ 02685 _argvec[2+2] = (unsigned long)arg2; \ 02686 _argvec[2+3] = (unsigned long)arg3; \ 02687 _argvec[2+4] = (unsigned long)arg4; \ 02688 _argvec[2+5] = (unsigned long)arg5; \ 02689 _argvec[2+6] = (unsigned long)arg6; \ 02690 _argvec[2+7] = (unsigned long)arg7; \ 02691 __asm__ volatile( \ 02692 "mr 11,%1\n\t" \ 02693 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 02694 "stw 2,-8(11)\n\t" /* save tocptr */ \ 02695 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 02696 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 02697 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 02698 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 02699 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 02700 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 02701 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 02702 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ 02703 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 02704 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02705 "mr 11,%1\n\t" \ 02706 "mr %0,3\n\t" \ 02707 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 02708 VG_CONTRACT_FRAME_BY(512) \ 02709 : /*out*/ "=r" (_res) \ 02710 : /*in*/ "r" (&_argvec[2]) \ 02711 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02712 ); \ 02713 lval = (__typeof__(lval)) _res; \ 02714 } while (0) 02715 02716 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 02717 arg7,arg8) \ 02718 do { \ 02719 volatile OrigFn _orig = (orig); \ 02720 volatile unsigned long _argvec[3+8]; \ 02721 volatile unsigned long _res; \ 02722 /* _argvec[0] holds current r2 across the call */ \ 02723 _argvec[1] = (unsigned long)_orig.r2; \ 02724 _argvec[2] = (unsigned long)_orig.nraddr; \ 02725 _argvec[2+1] = (unsigned long)arg1; \ 02726 _argvec[2+2] = (unsigned long)arg2; \ 02727 _argvec[2+3] = (unsigned long)arg3; \ 02728 _argvec[2+4] = (unsigned long)arg4; \ 02729 _argvec[2+5] = (unsigned long)arg5; \ 02730 _argvec[2+6] = (unsigned long)arg6; \ 02731 _argvec[2+7] = (unsigned long)arg7; \ 02732 _argvec[2+8] = (unsigned long)arg8; \ 02733 __asm__ volatile( \ 02734 "mr 11,%1\n\t" \ 02735 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 02736 "stw 2,-8(11)\n\t" /* save tocptr */ \ 02737 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 02738 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 02739 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 02740 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 02741 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 02742 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 02743 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 02744 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ 02745 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ 02746 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 02747 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02748 "mr 11,%1\n\t" \ 02749 "mr %0,3\n\t" \ 02750 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 02751 VG_CONTRACT_FRAME_BY(512) \ 02752 : /*out*/ "=r" (_res) \ 02753 : /*in*/ "r" (&_argvec[2]) \ 02754 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02755 ); \ 02756 lval = (__typeof__(lval)) _res; \ 02757 } while (0) 02758 02759 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 02760 arg7,arg8,arg9) \ 02761 do { \ 02762 volatile OrigFn _orig = (orig); \ 02763 volatile unsigned long _argvec[3+9]; \ 02764 volatile unsigned long _res; \ 02765 /* _argvec[0] holds current r2 across the call */ \ 02766 _argvec[1] = (unsigned long)_orig.r2; \ 02767 _argvec[2] = (unsigned long)_orig.nraddr; \ 02768 _argvec[2+1] = (unsigned long)arg1; \ 02769 _argvec[2+2] = (unsigned long)arg2; \ 02770 _argvec[2+3] = (unsigned long)arg3; \ 02771 _argvec[2+4] = (unsigned long)arg4; \ 02772 _argvec[2+5] = (unsigned long)arg5; \ 02773 _argvec[2+6] = (unsigned long)arg6; \ 02774 _argvec[2+7] = (unsigned long)arg7; \ 02775 _argvec[2+8] = (unsigned long)arg8; \ 02776 _argvec[2+9] = (unsigned long)arg9; \ 02777 __asm__ volatile( \ 02778 "mr 11,%1\n\t" \ 02779 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 02780 "stw 2,-8(11)\n\t" /* save tocptr */ \ 02781 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 02782 VG_EXPAND_FRAME_BY_trashes_r3(64) \ 02783 /* arg9 */ \ 02784 "lwz 3,36(11)\n\t" \ 02785 "stw 3,56(1)\n\t" \ 02786 /* args1-8 */ \ 02787 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 02788 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 02789 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 02790 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 02791 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 02792 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 02793 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ 02794 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ 02795 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 02796 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02797 "mr 11,%1\n\t" \ 02798 "mr %0,3\n\t" \ 02799 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 02800 VG_CONTRACT_FRAME_BY(64) \ 02801 VG_CONTRACT_FRAME_BY(512) \ 02802 : /*out*/ "=r" (_res) \ 02803 : /*in*/ "r" (&_argvec[2]) \ 02804 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02805 ); \ 02806 lval = (__typeof__(lval)) _res; \ 02807 } while (0) 02808 02809 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 02810 arg7,arg8,arg9,arg10) \ 02811 do { \ 02812 volatile OrigFn _orig = (orig); \ 02813 volatile unsigned long _argvec[3+10]; \ 02814 volatile unsigned long _res; \ 02815 /* _argvec[0] holds current r2 across the call */ \ 02816 _argvec[1] = (unsigned long)_orig.r2; \ 02817 _argvec[2] = (unsigned long)_orig.nraddr; \ 02818 _argvec[2+1] = (unsigned long)arg1; \ 02819 _argvec[2+2] = (unsigned long)arg2; \ 02820 _argvec[2+3] = (unsigned long)arg3; \ 02821 _argvec[2+4] = (unsigned long)arg4; \ 02822 _argvec[2+5] = (unsigned long)arg5; \ 02823 _argvec[2+6] = (unsigned long)arg6; \ 02824 _argvec[2+7] = (unsigned long)arg7; \ 02825 _argvec[2+8] = (unsigned long)arg8; \ 02826 _argvec[2+9] = (unsigned long)arg9; \ 02827 _argvec[2+10] = (unsigned long)arg10; \ 02828 __asm__ volatile( \ 02829 "mr 11,%1\n\t" \ 02830 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 02831 "stw 2,-8(11)\n\t" /* save tocptr */ \ 02832 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 02833 VG_EXPAND_FRAME_BY_trashes_r3(64) \ 02834 /* arg10 */ \ 02835 "lwz 3,40(11)\n\t" \ 02836 "stw 3,60(1)\n\t" \ 02837 /* arg9 */ \ 02838 "lwz 3,36(11)\n\t" \ 02839 "stw 3,56(1)\n\t" \ 02840 /* args1-8 */ \ 02841 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 02842 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 02843 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 02844 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 02845 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 02846 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 02847 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ 02848 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ 02849 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 02850 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02851 "mr 11,%1\n\t" \ 02852 "mr %0,3\n\t" \ 02853 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 02854 VG_CONTRACT_FRAME_BY(64) \ 02855 VG_CONTRACT_FRAME_BY(512) \ 02856 : /*out*/ "=r" (_res) \ 02857 : /*in*/ "r" (&_argvec[2]) \ 02858 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02859 ); \ 02860 lval = (__typeof__(lval)) _res; \ 02861 } while (0) 02862 02863 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 02864 arg7,arg8,arg9,arg10,arg11) \ 02865 do { \ 02866 volatile OrigFn _orig = (orig); \ 02867 volatile unsigned long _argvec[3+11]; \ 02868 volatile unsigned long _res; \ 02869 /* _argvec[0] holds current r2 across the call */ \ 02870 _argvec[1] = (unsigned long)_orig.r2; \ 02871 _argvec[2] = (unsigned long)_orig.nraddr; \ 02872 _argvec[2+1] = (unsigned long)arg1; \ 02873 _argvec[2+2] = (unsigned long)arg2; \ 02874 _argvec[2+3] = (unsigned long)arg3; \ 02875 _argvec[2+4] = (unsigned long)arg4; \ 02876 _argvec[2+5] = (unsigned long)arg5; \ 02877 _argvec[2+6] = (unsigned long)arg6; \ 02878 _argvec[2+7] = (unsigned long)arg7; \ 02879 _argvec[2+8] = (unsigned long)arg8; \ 02880 _argvec[2+9] = (unsigned long)arg9; \ 02881 _argvec[2+10] = (unsigned long)arg10; \ 02882 _argvec[2+11] = (unsigned long)arg11; \ 02883 __asm__ volatile( \ 02884 "mr 11,%1\n\t" \ 02885 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 02886 "stw 2,-8(11)\n\t" /* save tocptr */ \ 02887 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 02888 VG_EXPAND_FRAME_BY_trashes_r3(72) \ 02889 /* arg11 */ \ 02890 "lwz 3,44(11)\n\t" \ 02891 "stw 3,64(1)\n\t" \ 02892 /* arg10 */ \ 02893 "lwz 3,40(11)\n\t" \ 02894 "stw 3,60(1)\n\t" \ 02895 /* arg9 */ \ 02896 "lwz 3,36(11)\n\t" \ 02897 "stw 3,56(1)\n\t" \ 02898 /* args1-8 */ \ 02899 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 02900 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 02901 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 02902 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 02903 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 02904 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 02905 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ 02906 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ 02907 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 02908 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02909 "mr 11,%1\n\t" \ 02910 "mr %0,3\n\t" \ 02911 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 02912 VG_CONTRACT_FRAME_BY(72) \ 02913 VG_CONTRACT_FRAME_BY(512) \ 02914 : /*out*/ "=r" (_res) \ 02915 : /*in*/ "r" (&_argvec[2]) \ 02916 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02917 ); \ 02918 lval = (__typeof__(lval)) _res; \ 02919 } while (0) 02920 02921 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 02922 arg7,arg8,arg9,arg10,arg11,arg12) \ 02923 do { \ 02924 volatile OrigFn _orig = (orig); \ 02925 volatile unsigned long _argvec[3+12]; \ 02926 volatile unsigned long _res; \ 02927 /* _argvec[0] holds current r2 across the call */ \ 02928 _argvec[1] = (unsigned long)_orig.r2; \ 02929 _argvec[2] = (unsigned long)_orig.nraddr; \ 02930 _argvec[2+1] = (unsigned long)arg1; \ 02931 _argvec[2+2] = (unsigned long)arg2; \ 02932 _argvec[2+3] = (unsigned long)arg3; \ 02933 _argvec[2+4] = (unsigned long)arg4; \ 02934 _argvec[2+5] = (unsigned long)arg5; \ 02935 _argvec[2+6] = (unsigned long)arg6; \ 02936 _argvec[2+7] = (unsigned long)arg7; \ 02937 _argvec[2+8] = (unsigned long)arg8; \ 02938 _argvec[2+9] = (unsigned long)arg9; \ 02939 _argvec[2+10] = (unsigned long)arg10; \ 02940 _argvec[2+11] = (unsigned long)arg11; \ 02941 _argvec[2+12] = (unsigned long)arg12; \ 02942 __asm__ volatile( \ 02943 "mr 11,%1\n\t" \ 02944 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 02945 "stw 2,-8(11)\n\t" /* save tocptr */ \ 02946 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 02947 VG_EXPAND_FRAME_BY_trashes_r3(72) \ 02948 /* arg12 */ \ 02949 "lwz 3,48(11)\n\t" \ 02950 "stw 3,68(1)\n\t" \ 02951 /* arg11 */ \ 02952 "lwz 3,44(11)\n\t" \ 02953 "stw 3,64(1)\n\t" \ 02954 /* arg10 */ \ 02955 "lwz 3,40(11)\n\t" \ 02956 "stw 3,60(1)\n\t" \ 02957 /* arg9 */ \ 02958 "lwz 3,36(11)\n\t" \ 02959 "stw 3,56(1)\n\t" \ 02960 /* args1-8 */ \ 02961 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 02962 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 02963 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 02964 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 02965 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 02966 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 02967 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ 02968 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ 02969 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 02970 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 02971 "mr 11,%1\n\t" \ 02972 "mr %0,3\n\t" \ 02973 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 02974 VG_CONTRACT_FRAME_BY(72) \ 02975 VG_CONTRACT_FRAME_BY(512) \ 02976 : /*out*/ "=r" (_res) \ 02977 : /*in*/ "r" (&_argvec[2]) \ 02978 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 02979 ); \ 02980 lval = (__typeof__(lval)) _res; \ 02981 } while (0) 02982 02983 #endif /* PLAT_ppc32_aix5 */ 02984 02985 /* ------------------------ ppc64-aix5 ------------------------- */ 02986 02987 #if defined(PLAT_ppc64_aix5) 02988 02989 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ 02990 02991 /* These regs are trashed by the hidden call. */ 02992 #define __CALLER_SAVED_REGS \ 02993 "lr", "ctr", "xer", \ 02994 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ 02995 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ 02996 "r11", "r12", "r13" 02997 02998 /* Expand the stack frame, copying enough info that unwinding 02999 still works. Trashes r3. */ 03000 03001 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \ 03002 "addi 1,1,-" #_n_fr "\n\t" \ 03003 "ld 3," #_n_fr "(1)\n\t" \ 03004 "std 3,0(1)\n\t" 03005 03006 #define VG_CONTRACT_FRAME_BY(_n_fr) \ 03007 "addi 1,1," #_n_fr "\n\t" 03008 03009 /* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned 03010 long) == 8. */ 03011 03012 #define CALL_FN_W_v(lval, orig) \ 03013 do { \ 03014 volatile OrigFn _orig = (orig); \ 03015 volatile unsigned long _argvec[3+0]; \ 03016 volatile unsigned long _res; \ 03017 /* _argvec[0] holds current r2 across the call */ \ 03018 _argvec[1] = (unsigned long)_orig.r2; \ 03019 _argvec[2] = (unsigned long)_orig.nraddr; \ 03020 __asm__ volatile( \ 03021 "mr 11,%1\n\t" \ 03022 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 03023 "std 2,-16(11)\n\t" /* save tocptr */ \ 03024 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 03025 "ld 11, 0(11)\n\t" /* target->r11 */ \ 03026 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 03027 "mr 11,%1\n\t" \ 03028 "mr %0,3\n\t" \ 03029 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 03030 VG_CONTRACT_FRAME_BY(512) \ 03031 : /*out*/ "=r" (_res) \ 03032 : /*in*/ "r" (&_argvec[2]) \ 03033 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 03034 ); \ 03035 lval = (__typeof__(lval)) _res; \ 03036 } while (0) 03037 03038 #define CALL_FN_W_W(lval, orig, arg1) \ 03039 do { \ 03040 volatile OrigFn _orig = (orig); \ 03041 volatile unsigned long _argvec[3+1]; \ 03042 volatile unsigned long _res; \ 03043 /* _argvec[0] holds current r2 across the call */ \ 03044 _argvec[1] = (unsigned long)_orig.r2; \ 03045 _argvec[2] = (unsigned long)_orig.nraddr; \ 03046 _argvec[2+1] = (unsigned long)arg1; \ 03047 __asm__ volatile( \ 03048 "mr 11,%1\n\t" \ 03049 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 03050 "std 2,-16(11)\n\t" /* save tocptr */ \ 03051 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 03052 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 03053 "ld 11, 0(11)\n\t" /* target->r11 */ \ 03054 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 03055 "mr 11,%1\n\t" \ 03056 "mr %0,3\n\t" \ 03057 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 03058 VG_CONTRACT_FRAME_BY(512) \ 03059 : /*out*/ "=r" (_res) \ 03060 : /*in*/ "r" (&_argvec[2]) \ 03061 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 03062 ); \ 03063 lval = (__typeof__(lval)) _res; \ 03064 } while (0) 03065 03066 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 03067 do { \ 03068 volatile OrigFn _orig = (orig); \ 03069 volatile unsigned long _argvec[3+2]; \ 03070 volatile unsigned long _res; \ 03071 /* _argvec[0] holds current r2 across the call */ \ 03072 _argvec[1] = (unsigned long)_orig.r2; \ 03073 _argvec[2] = (unsigned long)_orig.nraddr; \ 03074 _argvec[2+1] = (unsigned long)arg1; \ 03075 _argvec[2+2] = (unsigned long)arg2; \ 03076 __asm__ volatile( \ 03077 "mr 11,%1\n\t" \ 03078 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 03079 "std 2,-16(11)\n\t" /* save tocptr */ \ 03080 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 03081 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 03082 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 03083 "ld 11, 0(11)\n\t" /* target->r11 */ \ 03084 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 03085 "mr 11,%1\n\t" \ 03086 "mr %0,3\n\t" \ 03087 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 03088 VG_CONTRACT_FRAME_BY(512) \ 03089 : /*out*/ "=r" (_res) \ 03090 : /*in*/ "r" (&_argvec[2]) \ 03091 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 03092 ); \ 03093 lval = (__typeof__(lval)) _res; \ 03094 } while (0) 03095 03096 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 03097 do { \ 03098 volatile OrigFn _orig = (orig); \ 03099 volatile unsigned long _argvec[3+3]; \ 03100 volatile unsigned long _res; \ 03101 /* _argvec[0] holds current r2 across the call */ \ 03102 _argvec[1] = (unsigned long)_orig.r2; \ 03103 _argvec[2] = (unsigned long)_orig.nraddr; \ 03104 _argvec[2+1] = (unsigned long)arg1; \ 03105 _argvec[2+2] = (unsigned long)arg2; \ 03106 _argvec[2+3] = (unsigned long)arg3; \ 03107 __asm__ volatile( \ 03108 "mr 11,%1\n\t" \ 03109 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 03110 "std 2,-16(11)\n\t" /* save tocptr */ \ 03111 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 03112 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 03113 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 03114 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 03115 "ld 11, 0(11)\n\t" /* target->r11 */ \ 03116 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 03117 "mr 11,%1\n\t" \ 03118 "mr %0,3\n\t" \ 03119 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 03120 VG_CONTRACT_FRAME_BY(512) \ 03121 : /*out*/ "=r" (_res) \ 03122 : /*in*/ "r" (&_argvec[2]) \ 03123 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 03124 ); \ 03125 lval = (__typeof__(lval)) _res; \ 03126 } while (0) 03127 03128 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 03129 do { \ 03130 volatile OrigFn _orig = (orig); \ 03131 volatile unsigned long _argvec[3+4]; \ 03132 volatile unsigned long _res; \ 03133 /* _argvec[0] holds current r2 across the call */ \ 03134 _argvec[1] = (unsigned long)_orig.r2; \ 03135 _argvec[2] = (unsigned long)_orig.nraddr; \ 03136 _argvec[2+1] = (unsigned long)arg1; \ 03137 _argvec[2+2] = (unsigned long)arg2; \ 03138 _argvec[2+3] = (unsigned long)arg3; \ 03139 _argvec[2+4] = (unsigned long)arg4; \ 03140 __asm__ volatile( \ 03141 "mr 11,%1\n\t" \ 03142 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 03143 "std 2,-16(11)\n\t" /* save tocptr */ \ 03144 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 03145 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 03146 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 03147 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 03148 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 03149 "ld 11, 0(11)\n\t" /* target->r11 */ \ 03150 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 03151 "mr 11,%1\n\t" \ 03152 "mr %0,3\n\t" \ 03153 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 03154 VG_CONTRACT_FRAME_BY(512) \ 03155 : /*out*/ "=r" (_res) \ 03156 : /*in*/ "r" (&_argvec[2]) \ 03157 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 03158 ); \ 03159 lval = (__typeof__(lval)) _res; \ 03160 } while (0) 03161 03162 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 03163 do { \ 03164 volatile OrigFn _orig = (orig); \ 03165 volatile unsigned long _argvec[3+5]; \ 03166 volatile unsigned long _res; \ 03167 /* _argvec[0] holds current r2 across the call */ \ 03168 _argvec[1] = (unsigned long)_orig.r2; \ 03169 _argvec[2] = (unsigned long)_orig.nraddr; \ 03170 _argvec[2+1] = (unsigned long)arg1; \ 03171 _argvec[2+2] = (unsigned long)arg2; \ 03172 _argvec[2+3] = (unsigned long)arg3; \ 03173 _argvec[2+4] = (unsigned long)arg4; \ 03174 _argvec[2+5] = (unsigned long)arg5; \ 03175 __asm__ volatile( \ 03176 "mr 11,%1\n\t" \ 03177 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 03178 "std 2,-16(11)\n\t" /* save tocptr */ \ 03179 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 03180 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 03181 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 03182 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 03183 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 03184 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 03185 "ld 11, 0(11)\n\t" /* target->r11 */ \ 03186 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 03187 "mr 11,%1\n\t" \ 03188 "mr %0,3\n\t" \ 03189 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 03190 VG_CONTRACT_FRAME_BY(512) \ 03191 : /*out*/ "=r" (_res) \ 03192 : /*in*/ "r" (&_argvec[2]) \ 03193 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 03194 ); \ 03195 lval = (__typeof__(lval)) _res; \ 03196 } while (0) 03197 03198 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 03199 do { \ 03200 volatile OrigFn _orig = (orig); \ 03201 volatile unsigned long _argvec[3+6]; \ 03202 volatile unsigned long _res; \ 03203 /* _argvec[0] holds current r2 across the call */ \ 03204 _argvec[1] = (unsigned long)_orig.r2; \ 03205 _argvec[2] = (unsigned long)_orig.nraddr; \ 03206 _argvec[2+1] = (unsigned long)arg1; \ 03207 _argvec[2+2] = (unsigned long)arg2; \ 03208 _argvec[2+3] = (unsigned long)arg3; \ 03209 _argvec[2+4] = (unsigned long)arg4; \ 03210 _argvec[2+5] = (unsigned long)arg5; \ 03211 _argvec[2+6] = (unsigned long)arg6; \ 03212 __asm__ volatile( \ 03213 "mr 11,%1\n\t" \ 03214 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 03215 "std 2,-16(11)\n\t" /* save tocptr */ \ 03216 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 03217 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 03218 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 03219 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 03220 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 03221 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 03222 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 03223 "ld 11, 0(11)\n\t" /* target->r11 */ \ 03224 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 03225 "mr 11,%1\n\t" \ 03226 "mr %0,3\n\t" \ 03227 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 03228 VG_CONTRACT_FRAME_BY(512) \ 03229 : /*out*/ "=r" (_res) \ 03230 : /*in*/ "r" (&_argvec[2]) \ 03231 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 03232 ); \ 03233 lval = (__typeof__(lval)) _res; \ 03234 } while (0) 03235 03236 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 03237 arg7) \ 03238 do { \ 03239 volatile OrigFn _orig = (orig); \ 03240 volatile unsigned long _argvec[3+7]; \ 03241 volatile unsigned long _res; \ 03242 /* _argvec[0] holds current r2 across the call */ \ 03243 _argvec[1] = (unsigned long)_orig.r2; \ 03244 _argvec[2] = (unsigned long)_orig.nraddr; \ 03245 _argvec[2+1] = (unsigned long)arg1; \ 03246 _argvec[2+2] = (unsigned long)arg2; \ 03247 _argvec[2+3] = (unsigned long)arg3; \ 03248 _argvec[2+4] = (unsigned long)arg4; \ 03249 _argvec[2+5] = (unsigned long)arg5; \ 03250 _argvec[2+6] = (unsigned long)arg6; \ 03251 _argvec[2+7] = (unsigned long)arg7; \ 03252 __asm__ volatile( \ 03253 "mr 11,%1\n\t" \ 03254 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 03255 "std 2,-16(11)\n\t" /* save tocptr */ \ 03256 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 03257 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 03258 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 03259 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 03260 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 03261 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 03262 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 03263 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 03264 "ld 11, 0(11)\n\t" /* target->r11 */ \ 03265 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 03266 "mr 11,%1\n\t" \ 03267 "mr %0,3\n\t" \ 03268 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 03269 VG_CONTRACT_FRAME_BY(512) \ 03270 : /*out*/ "=r" (_res) \ 03271 : /*in*/ "r" (&_argvec[2]) \ 03272 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 03273 ); \ 03274 lval = (__typeof__(lval)) _res; \ 03275 } while (0) 03276 03277 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 03278 arg7,arg8) \ 03279 do { \ 03280 volatile OrigFn _orig = (orig); \ 03281 volatile unsigned long _argvec[3+8]; \ 03282 volatile unsigned long _res; \ 03283 /* _argvec[0] holds current r2 across the call */ \ 03284 _argvec[1] = (unsigned long)_orig.r2; \ 03285 _argvec[2] = (unsigned long)_orig.nraddr; \ 03286 _argvec[2+1] = (unsigned long)arg1; \ 03287 _argvec[2+2] = (unsigned long)arg2; \ 03288 _argvec[2+3] = (unsigned long)arg3; \ 03289 _argvec[2+4] = (unsigned long)arg4; \ 03290 _argvec[2+5] = (unsigned long)arg5; \ 03291 _argvec[2+6] = (unsigned long)arg6; \ 03292 _argvec[2+7] = (unsigned long)arg7; \ 03293 _argvec[2+8] = (unsigned long)arg8; \ 03294 __asm__ volatile( \ 03295 "mr 11,%1\n\t" \ 03296 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 03297 "std 2,-16(11)\n\t" /* save tocptr */ \ 03298 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 03299 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 03300 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 03301 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 03302 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 03303 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 03304 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 03305 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 03306 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 03307 "ld 11, 0(11)\n\t" /* target->r11 */ \ 03308 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 03309 "mr 11,%1\n\t" \ 03310 "mr %0,3\n\t" \ 03311 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 03312 VG_CONTRACT_FRAME_BY(512) \ 03313 : /*out*/ "=r" (_res) \ 03314 : /*in*/ "r" (&_argvec[2]) \ 03315 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 03316 ); \ 03317 lval = (__typeof__(lval)) _res; \ 03318 } while (0) 03319 03320 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 03321 arg7,arg8,arg9) \ 03322 do { \ 03323 volatile OrigFn _orig = (orig); \ 03324 volatile unsigned long _argvec[3+9]; \ 03325 volatile unsigned long _res; \ 03326 /* _argvec[0] holds current r2 across the call */ \ 03327 _argvec[1] = (unsigned long)_orig.r2; \ 03328 _argvec[2] = (unsigned long)_orig.nraddr; \ 03329 _argvec[2+1] = (unsigned long)arg1; \ 03330 _argvec[2+2] = (unsigned long)arg2; \ 03331 _argvec[2+3] = (unsigned long)arg3; \ 03332 _argvec[2+4] = (unsigned long)arg4; \ 03333 _argvec[2+5] = (unsigned long)arg5; \ 03334 _argvec[2+6] = (unsigned long)arg6; \ 03335 _argvec[2+7] = (unsigned long)arg7; \ 03336 _argvec[2+8] = (unsigned long)arg8; \ 03337 _argvec[2+9] = (unsigned long)arg9; \ 03338 __asm__ volatile( \ 03339 "mr 11,%1\n\t" \ 03340 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 03341 "std 2,-16(11)\n\t" /* save tocptr */ \ 03342 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 03343 VG_EXPAND_FRAME_BY_trashes_r3(128) \ 03344 /* arg9 */ \ 03345 "ld 3,72(11)\n\t" \ 03346 "std 3,112(1)\n\t" \ 03347 /* args1-8 */ \ 03348 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 03349 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 03350 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 03351 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 03352 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 03353 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 03354 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 03355 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 03356 "ld 11, 0(11)\n\t" /* target->r11 */ \ 03357 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 03358 "mr 11,%1\n\t" \ 03359 "mr %0,3\n\t" \ 03360 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 03361 VG_CONTRACT_FRAME_BY(128) \ 03362 VG_CONTRACT_FRAME_BY(512) \ 03363 : /*out*/ "=r" (_res) \ 03364 : /*in*/ "r" (&_argvec[2]) \ 03365 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 03366 ); \ 03367 lval = (__typeof__(lval)) _res; \ 03368 } while (0) 03369 03370 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 03371 arg7,arg8,arg9,arg10) \ 03372 do { \ 03373 volatile OrigFn _orig = (orig); \ 03374 volatile unsigned long _argvec[3+10]; \ 03375 volatile unsigned long _res; \ 03376 /* _argvec[0] holds current r2 across the call */ \ 03377 _argvec[1] = (unsigned long)_orig.r2; \ 03378 _argvec[2] = (unsigned long)_orig.nraddr; \ 03379 _argvec[2+1] = (unsigned long)arg1; \ 03380 _argvec[2+2] = (unsigned long)arg2; \ 03381 _argvec[2+3] = (unsigned long)arg3; \ 03382 _argvec[2+4] = (unsigned long)arg4; \ 03383 _argvec[2+5] = (unsigned long)arg5; \ 03384 _argvec[2+6] = (unsigned long)arg6; \ 03385 _argvec[2+7] = (unsigned long)arg7; \ 03386 _argvec[2+8] = (unsigned long)arg8; \ 03387 _argvec[2+9] = (unsigned long)arg9; \ 03388 _argvec[2+10] = (unsigned long)arg10; \ 03389 __asm__ volatile( \ 03390 "mr 11,%1\n\t" \ 03391 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 03392 "std 2,-16(11)\n\t" /* save tocptr */ \ 03393 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 03394 VG_EXPAND_FRAME_BY_trashes_r3(128) \ 03395 /* arg10 */ \ 03396 "ld 3,80(11)\n\t" \ 03397 "std 3,120(1)\n\t" \ 03398 /* arg9 */ \ 03399 "ld 3,72(11)\n\t" \ 03400 "std 3,112(1)\n\t" \ 03401 /* args1-8 */ \ 03402 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 03403 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 03404 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 03405 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 03406 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 03407 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 03408 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 03409 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 03410 "ld 11, 0(11)\n\t" /* target->r11 */ \ 03411 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 03412 "mr 11,%1\n\t" \ 03413 "mr %0,3\n\t" \ 03414 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 03415 VG_CONTRACT_FRAME_BY(128) \ 03416 VG_CONTRACT_FRAME_BY(512) \ 03417 : /*out*/ "=r" (_res) \ 03418 : /*in*/ "r" (&_argvec[2]) \ 03419 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 03420 ); \ 03421 lval = (__typeof__(lval)) _res; \ 03422 } while (0) 03423 03424 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 03425 arg7,arg8,arg9,arg10,arg11) \ 03426 do { \ 03427 volatile OrigFn _orig = (orig); \ 03428 volatile unsigned long _argvec[3+11]; \ 03429 volatile unsigned long _res; \ 03430 /* _argvec[0] holds current r2 across the call */ \ 03431 _argvec[1] = (unsigned long)_orig.r2; \ 03432 _argvec[2] = (unsigned long)_orig.nraddr; \ 03433 _argvec[2+1] = (unsigned long)arg1; \ 03434 _argvec[2+2] = (unsigned long)arg2; \ 03435 _argvec[2+3] = (unsigned long)arg3; \ 03436 _argvec[2+4] = (unsigned long)arg4; \ 03437 _argvec[2+5] = (unsigned long)arg5; \ 03438 _argvec[2+6] = (unsigned long)arg6; \ 03439 _argvec[2+7] = (unsigned long)arg7; \ 03440 _argvec[2+8] = (unsigned long)arg8; \ 03441 _argvec[2+9] = (unsigned long)arg9; \ 03442 _argvec[2+10] = (unsigned long)arg10; \ 03443 _argvec[2+11] = (unsigned long)arg11; \ 03444 __asm__ volatile( \ 03445 "mr 11,%1\n\t" \ 03446 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 03447 "std 2,-16(11)\n\t" /* save tocptr */ \ 03448 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 03449 VG_EXPAND_FRAME_BY_trashes_r3(144) \ 03450 /* arg11 */ \ 03451 "ld 3,88(11)\n\t" \ 03452 "std 3,128(1)\n\t" \ 03453 /* arg10 */ \ 03454 "ld 3,80(11)\n\t" \ 03455 "std 3,120(1)\n\t" \ 03456 /* arg9 */ \ 03457 "ld 3,72(11)\n\t" \ 03458 "std 3,112(1)\n\t" \ 03459 /* args1-8 */ \ 03460 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 03461 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 03462 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 03463 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 03464 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 03465 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 03466 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 03467 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 03468 "ld 11, 0(11)\n\t" /* target->r11 */ \ 03469 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 03470 "mr 11,%1\n\t" \ 03471 "mr %0,3\n\t" \ 03472 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 03473 VG_CONTRACT_FRAME_BY(144) \ 03474 VG_CONTRACT_FRAME_BY(512) \ 03475 : /*out*/ "=r" (_res) \ 03476 : /*in*/ "r" (&_argvec[2]) \ 03477 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 03478 ); \ 03479 lval = (__typeof__(lval)) _res; \ 03480 } while (0) 03481 03482 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 03483 arg7,arg8,arg9,arg10,arg11,arg12) \ 03484 do { \ 03485 volatile OrigFn _orig = (orig); \ 03486 volatile unsigned long _argvec[3+12]; \ 03487 volatile unsigned long _res; \ 03488 /* _argvec[0] holds current r2 across the call */ \ 03489 _argvec[1] = (unsigned long)_orig.r2; \ 03490 _argvec[2] = (unsigned long)_orig.nraddr; \ 03491 _argvec[2+1] = (unsigned long)arg1; \ 03492 _argvec[2+2] = (unsigned long)arg2; \ 03493 _argvec[2+3] = (unsigned long)arg3; \ 03494 _argvec[2+4] = (unsigned long)arg4; \ 03495 _argvec[2+5] = (unsigned long)arg5; \ 03496 _argvec[2+6] = (unsigned long)arg6; \ 03497 _argvec[2+7] = (unsigned long)arg7; \ 03498 _argvec[2+8] = (unsigned long)arg8; \ 03499 _argvec[2+9] = (unsigned long)arg9; \ 03500 _argvec[2+10] = (unsigned long)arg10; \ 03501 _argvec[2+11] = (unsigned long)arg11; \ 03502 _argvec[2+12] = (unsigned long)arg12; \ 03503 __asm__ volatile( \ 03504 "mr 11,%1\n\t" \ 03505 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 03506 "std 2,-16(11)\n\t" /* save tocptr */ \ 03507 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 03508 VG_EXPAND_FRAME_BY_trashes_r3(144) \ 03509 /* arg12 */ \ 03510 "ld 3,96(11)\n\t" \ 03511 "std 3,136(1)\n\t" \ 03512 /* arg11 */ \ 03513 "ld 3,88(11)\n\t" \ 03514 "std 3,128(1)\n\t" \ 03515 /* arg10 */ \ 03516 "ld 3,80(11)\n\t" \ 03517 "std 3,120(1)\n\t" \ 03518 /* arg9 */ \ 03519 "ld 3,72(11)\n\t" \ 03520 "std 3,112(1)\n\t" \ 03521 /* args1-8 */ \ 03522 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 03523 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 03524 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 03525 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 03526 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 03527 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 03528 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 03529 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 03530 "ld 11, 0(11)\n\t" /* target->r11 */ \ 03531 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 03532 "mr 11,%1\n\t" \ 03533 "mr %0,3\n\t" \ 03534 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 03535 VG_CONTRACT_FRAME_BY(144) \ 03536 VG_CONTRACT_FRAME_BY(512) \ 03537 : /*out*/ "=r" (_res) \ 03538 : /*in*/ "r" (&_argvec[2]) \ 03539 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 03540 ); \ 03541 lval = (__typeof__(lval)) _res; \ 03542 } while (0) 03543 03544 #endif /* PLAT_ppc64_aix5 */ 03545 03546 03547 /* ------------------------------------------------------------------ */ 03548 /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */ 03549 /* */ 03550 /* ------------------------------------------------------------------ */ 03551 03552 /* Some request codes. There are many more of these, but most are not 03553 exposed to end-user view. These are the public ones, all of the 03554 form 0x1000 + small_number. 03555 03556 Core ones are in the range 0x00000000--0x0000ffff. The non-public 03557 ones start at 0x2000. 03558 */ 03559 03560 /* These macros are used by tools -- they must be public, but don't 03561 embed them into other programs. */ 03562 #define VG_USERREQ_TOOL_BASE(a,b) \ 03563 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16)) 03564 #define VG_IS_TOOL_USERREQ(a, b, v) \ 03565 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000)) 03566 03567 /* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! 03568 This enum comprises an ABI exported by Valgrind to programs 03569 which use client requests. DO NOT CHANGE THE ORDER OF THESE 03570 ENTRIES, NOR DELETE ANY -- add new ones at the end. */ 03571 typedef 03572 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001, 03573 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002, 03574 03575 /* These allow any function to be called from the simulated 03576 CPU but run on the real CPU. Nb: the first arg passed to 03577 the function is always the ThreadId of the running 03578 thread! So CLIENT_CALL0 actually requires a 1 arg 03579 function, etc. */ 03580 VG_USERREQ__CLIENT_CALL0 = 0x1101, 03581 VG_USERREQ__CLIENT_CALL1 = 0x1102, 03582 VG_USERREQ__CLIENT_CALL2 = 0x1103, 03583 VG_USERREQ__CLIENT_CALL3 = 0x1104, 03584 03585 /* Can be useful in regression testing suites -- eg. can 03586 send Valgrind's output to /dev/null and still count 03587 errors. */ 03588 VG_USERREQ__COUNT_ERRORS = 0x1201, 03589 03590 /* These are useful and can be interpreted by any tool that 03591 tracks malloc() et al, by using vg_replace_malloc.c. */ 03592 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301, 03593 VG_USERREQ__FREELIKE_BLOCK = 0x1302, 03594 /* Memory pool support. */ 03595 VG_USERREQ__CREATE_MEMPOOL = 0x1303, 03596 VG_USERREQ__DESTROY_MEMPOOL = 0x1304, 03597 VG_USERREQ__MEMPOOL_ALLOC = 0x1305, 03598 VG_USERREQ__MEMPOOL_FREE = 0x1306, 03599 VG_USERREQ__MEMPOOL_TRIM = 0x1307, 03600 VG_USERREQ__MOVE_MEMPOOL = 0x1308, 03601 VG_USERREQ__MEMPOOL_CHANGE = 0x1309, 03602 VG_USERREQ__MEMPOOL_EXISTS = 0x130a, 03603 03604 /* Allow printfs to valgrind log. */ 03605 VG_USERREQ__PRINTF = 0x1401, 03606 VG_USERREQ__PRINTF_BACKTRACE = 0x1402, 03607 03608 /* Stack support. */ 03609 VG_USERREQ__STACK_REGISTER = 0x1501, 03610 VG_USERREQ__STACK_DEREGISTER = 0x1502, 03611 VG_USERREQ__STACK_CHANGE = 0x1503 03612 } Vg_ClientRequest; 03613 03614 #if !defined(__GNUC__) 03615 # define __extension__ /* */ 03616 #endif 03617 03618 /* Returns the number of Valgrinds this code is running under. That 03619 is, 0 if running natively, 1 if running under Valgrind, 2 if 03620 running under Valgrind which is running under another Valgrind, 03621 etc. */ 03622 #define RUNNING_ON_VALGRIND __extension__ \ 03623 ({unsigned int _qzz_res; \ 03624 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \ 03625 VG_USERREQ__RUNNING_ON_VALGRIND, \ 03626 0, 0, 0, 0, 0); \ 03627 _qzz_res; \ 03628 }) 03629 03630 03631 /* Discard translation of code in the range [_qzz_addr .. _qzz_addr + 03632 _qzz_len - 1]. Useful if you are debugging a JITter or some such, 03633 since it provides a way to make sure valgrind will retranslate the 03634 invalidated area. Returns no value. */ 03635 #define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \ 03636 {unsigned int _qzz_res; \ 03637 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 03638 VG_USERREQ__DISCARD_TRANSLATIONS, \ 03639 _qzz_addr, _qzz_len, 0, 0, 0); \ 03640 } 03641 03642 03643 /* These requests are for getting Valgrind itself to print something. 03644 Possibly with a backtrace. This is a really ugly hack. */ 03645 03646 #if defined(NVALGRIND) 03647 03648 # define VALGRIND_PRINTF(...) 03649 # define VALGRIND_PRINTF_BACKTRACE(...) 03650 03651 #else /* NVALGRIND */ 03652 03653 /* Modern GCC will optimize the static routine out if unused, 03654 and unused attribute will shut down warnings about it. */ 03655 static int VALGRIND_PRINTF(const char *format, ...) 03656 __attribute__((format(__printf__, 1, 2), __unused__)); 03657 static int 03658 VALGRIND_PRINTF(const char *format, ...) 03659 { 03660 unsigned long _qzz_res; 03661 va_list vargs; 03662 va_start(vargs, format); 03663 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF, 03664 (unsigned long)format, (unsigned long)vargs, 03665 0, 0, 0); 03666 va_end(vargs); 03667 return (int)_qzz_res; 03668 } 03669 03670 static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...) 03671 __attribute__((format(__printf__, 1, 2), __unused__)); 03672 static int 03673 VALGRIND_PRINTF_BACKTRACE(const char *format, ...) 03674 { 03675 unsigned long _qzz_res; 03676 va_list vargs; 03677 va_start(vargs, format); 03678 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE, 03679 (unsigned long)format, (unsigned long)vargs, 03680 0, 0, 0); 03681 va_end(vargs); 03682 return (int)_qzz_res; 03683 } 03684 03685 #endif /* NVALGRIND */ 03686 03687 03688 /* These requests allow control to move from the simulated CPU to the 03689 real CPU, calling an arbitary function. 03690 03691 Note that the current ThreadId is inserted as the first argument. 03692 So this call: 03693 03694 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2) 03695 03696 requires f to have this signature: 03697 03698 Word f(Word tid, Word arg1, Word arg2) 03699 03700 where "Word" is a word-sized type. 03701 03702 Note that these client requests are not entirely reliable. For example, 03703 if you call a function with them that subsequently calls printf(), 03704 there's a high chance Valgrind will crash. Generally, your prospects of 03705 these working are made higher if the called function does not refer to 03706 any global variables, and does not refer to any libc or other functions 03707 (printf et al). Any kind of entanglement with libc or dynamic linking is 03708 likely to have a bad outcome, for tricky reasons which we've grappled 03709 with a lot in the past. 03710 */ 03711 #define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \ 03712 __extension__ \ 03713 ({unsigned long _qyy_res; \ 03714 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ 03715 VG_USERREQ__CLIENT_CALL0, \ 03716 _qyy_fn, \ 03717 0, 0, 0, 0); \ 03718 _qyy_res; \ 03719 }) 03720 03721 #define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \ 03722 __extension__ \ 03723 ({unsigned long _qyy_res; \ 03724 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ 03725 VG_USERREQ__CLIENT_CALL1, \ 03726 _qyy_fn, \ 03727 _qyy_arg1, 0, 0, 0); \ 03728 _qyy_res; \ 03729 }) 03730 03731 #define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \ 03732 __extension__ \ 03733 ({unsigned long _qyy_res; \ 03734 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ 03735 VG_USERREQ__CLIENT_CALL2, \ 03736 _qyy_fn, \ 03737 _qyy_arg1, _qyy_arg2, 0, 0); \ 03738 _qyy_res; \ 03739 }) 03740 03741 #define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \ 03742 __extension__ \ 03743 ({unsigned long _qyy_res; \ 03744 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ 03745 VG_USERREQ__CLIENT_CALL3, \ 03746 _qyy_fn, \ 03747 _qyy_arg1, _qyy_arg2, \ 03748 _qyy_arg3, 0); \ 03749 _qyy_res; \ 03750 }) 03751 03752 03753 /* Counts the number of errors that have been recorded by a tool. Nb: 03754 the tool must record the errors with VG_(maybe_record_error)() or 03755 VG_(unique_error)() for them to be counted. */ 03756 #define VALGRIND_COUNT_ERRORS \ 03757 __extension__ \ 03758 ({unsigned int _qyy_res; \ 03759 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ 03760 VG_USERREQ__COUNT_ERRORS, \ 03761 0, 0, 0, 0, 0); \ 03762 _qyy_res; \ 03763 }) 03764 03765 /* Mark a block of memory as having been allocated by a malloc()-like 03766 function. `addr' is the start of the usable block (ie. after any 03767 redzone) `rzB' is redzone size if the allocator can apply redzones; 03768 use '0' if not. Adding redzones makes it more likely Valgrind will spot 03769 block overruns. `is_zeroed' indicates if the memory is zeroed, as it is 03770 for calloc(). Put it immediately after the point where a block is 03771 allocated. 03772 03773 If you're using Memcheck: If you're allocating memory via superblocks, 03774 and then handing out small chunks of each superblock, if you don't have 03775 redzones on your small blocks, it's worth marking the superblock with 03776 VALGRIND_MAKE_MEM_NOACCESS when it's created, so that block overruns are 03777 detected. But if you can put redzones on, it's probably better to not do 03778 this, so that messages for small overruns are described in terms of the 03779 small block rather than the superblock (but if you have a big overrun 03780 that skips over a redzone, you could miss an error this way). See 03781 memcheck/tests/custom_alloc.c for an example. 03782 03783 WARNING: if your allocator uses malloc() or 'new' to allocate 03784 superblocks, rather than mmap() or brk(), this will not work properly -- 03785 you'll likely get assertion failures during leak detection. This is 03786 because Valgrind doesn't like seeing overlapping heap blocks. Sorry. 03787 03788 Nb: block must be freed via a free()-like function specified 03789 with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */ 03790 #define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ 03791 {unsigned int _qzz_res; \ 03792 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 03793 VG_USERREQ__MALLOCLIKE_BLOCK, \ 03794 addr, sizeB, rzB, is_zeroed, 0); \ 03795 } 03796 03797 /* Mark a block of memory as having been freed by a free()-like function. 03798 `rzB' is redzone size; it must match that given to 03799 VALGRIND_MALLOCLIKE_BLOCK. Memory not freed will be detected by the leak 03800 checker. Put it immediately after the point where the block is freed. */ 03801 #define VALGRIND_FREELIKE_BLOCK(addr, rzB) \ 03802 {unsigned int _qzz_res; \ 03803 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 03804 VG_USERREQ__FREELIKE_BLOCK, \ 03805 addr, rzB, 0, 0, 0); \ 03806 } 03807 03808 /* Create a memory pool. */ 03809 #define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \ 03810 {unsigned int _qzz_res; \ 03811 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 03812 VG_USERREQ__CREATE_MEMPOOL, \ 03813 pool, rzB, is_zeroed, 0, 0); \ 03814 } 03815 03816 /* Destroy a memory pool. */ 03817 #define VALGRIND_DESTROY_MEMPOOL(pool) \ 03818 {unsigned int _qzz_res; \ 03819 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 03820 VG_USERREQ__DESTROY_MEMPOOL, \ 03821 pool, 0, 0, 0, 0); \ 03822 } 03823 03824 /* Associate a piece of memory with a memory pool. */ 03825 #define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \ 03826 {unsigned int _qzz_res; \ 03827 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 03828 VG_USERREQ__MEMPOOL_ALLOC, \ 03829 pool, addr, size, 0, 0); \ 03830 } 03831 03832 /* Disassociate a piece of memory from a memory pool. */ 03833 #define VALGRIND_MEMPOOL_FREE(pool, addr) \ 03834 {unsigned int _qzz_res; \ 03835 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 03836 VG_USERREQ__MEMPOOL_FREE, \ 03837 pool, addr, 0, 0, 0); \ 03838 } 03839 03840 /* Disassociate any pieces outside a particular range. */ 03841 #define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \ 03842 {unsigned int _qzz_res; \ 03843 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 03844 VG_USERREQ__MEMPOOL_TRIM, \ 03845 pool, addr, size, 0, 0); \ 03846 } 03847 03848 /* Resize and/or move a piece associated with a memory pool. */ 03849 #define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \ 03850 {unsigned int _qzz_res; \ 03851 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 03852 VG_USERREQ__MOVE_MEMPOOL, \ 03853 poolA, poolB, 0, 0, 0); \ 03854 } 03855 03856 /* Resize and/or move a piece associated with a memory pool. */ 03857 #define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \ 03858 {unsigned int _qzz_res; \ 03859 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 03860 VG_USERREQ__MEMPOOL_CHANGE, \ 03861 pool, addrA, addrB, size, 0); \ 03862 } 03863 03864 /* Return 1 if a mempool exists, else 0. */ 03865 #define VALGRIND_MEMPOOL_EXISTS(pool) \ 03866 ({unsigned int _qzz_res; \ 03867 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 03868 VG_USERREQ__MEMPOOL_EXISTS, \ 03869 pool, 0, 0, 0, 0); \ 03870 _qzz_res; \ 03871 }) 03872 03873 /* Mark a piece of memory as being a stack. Returns a stack id. */ 03874 #define VALGRIND_STACK_REGISTER(start, end) \ 03875 ({unsigned int _qzz_res; \ 03876 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 03877 VG_USERREQ__STACK_REGISTER, \ 03878 start, end, 0, 0, 0); \ 03879 _qzz_res; \ 03880 }) 03881 03882 /* Unmark the piece of memory associated with a stack id as being a 03883 stack. */ 03884 #define VALGRIND_STACK_DEREGISTER(id) \ 03885 {unsigned int _qzz_res; \ 03886 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 03887 VG_USERREQ__STACK_DEREGISTER, \ 03888 id, 0, 0, 0, 0); \ 03889 } 03890 03891 /* Change the start and end address of the stack id. */ 03892 #define VALGRIND_STACK_CHANGE(id, start, end) \ 03893 {unsigned int _qzz_res; \ 03894 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 03895 VG_USERREQ__STACK_CHANGE, \ 03896 id, start, end, 0, 0); \ 03897 } 03898 03899 03900 #undef PLAT_x86_linux 03901 #undef PLAT_amd64_linux 03902 #undef PLAT_ppc32_linux 03903 #undef PLAT_ppc64_linux 03904 #undef PLAT_ppc32_aix5 03905 #undef PLAT_ppc64_aix5 03906 03907 #endif /* __VALGRIND_H */