1 #ifdef ANDROID 2 #include "include/valgrind.h" 3 #else 4 /* -*- c -*- 5 ---------------------------------------------------------------- 6 7 Notice that the following BSD-style license applies to this one 8 file (valgrind.h) only. The rest of Valgrind is licensed under the 9 terms of the GNU General Public License, version 2, unless 10 otherwise indicated. See the COPYING file in the source 11 distribution for details. 12 13 ---------------------------------------------------------------- 14 15 This file is part of Valgrind, a dynamic binary instrumentation 16 framework. 17 18 Copyright (C) 2000-2010 Julian Seward. All rights reserved. 19 20 Redistribution and use in source and binary forms, with or without 21 modification, are permitted provided that the following conditions 22 are met: 23 24 1. Redistributions of source code must retain the above copyright 25 notice, this list of conditions and the following disclaimer. 26 27 2. The origin of this software must not be misrepresented; you must 28 not claim that you wrote the original software. If you use this 29 software in a product, an acknowledgment in the product 30 documentation would be appreciated but is not required. 31 32 3. Altered source versions must be plainly marked as such, and must 33 not be misrepresented as being the original software. 34 35 4. The name of the author may not be used to endorse or promote 36 products derived from this software without specific prior written 37 permission. 38 39 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 40 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 41 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 42 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 43 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 44 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 45 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 46 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 47 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 48 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 49 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 50 51 ---------------------------------------------------------------- 52 53 Notice that the above BSD-style license applies to this one file 54 (valgrind.h) only. The entire rest of Valgrind is licensed under 55 the terms of the GNU General Public License, version 2. See the 56 COPYING file in the source distribution for details. 57 58 ---------------------------------------------------------------- 59 */ 60 61 62 /* This file is for inclusion into client (your!) code. 63 64 You can use these macros to manipulate and query Valgrind's 65 execution inside your own programs. 66 67 The resulting executables will still run without Valgrind, just a 68 little bit more slowly than they otherwise would, but otherwise 69 unchanged. When not running on valgrind, each client request 70 consumes very few (eg. 7) instructions, so the resulting performance 71 loss is negligible unless you plan to execute client requests 72 millions of times per second. Nevertheless, if that is still a 73 problem, you can compile with the NVALGRIND symbol defined (gcc 74 -DNVALGRIND) so that client requests are not even compiled in. */ 75 76 #ifndef __VALGRIND_H 77 #define __VALGRIND_H 78 79 80 /* ------------------------------------------------------------------ */ 81 /* VERSION NUMBER OF VALGRIND */ 82 /* ------------------------------------------------------------------ */ 83 84 /* Specify Valgrind's version number, so that user code can 85 conditionally compile based on our version number. Note that these 86 were introduced at version 3.6 and so do not exist in version 3.5 87 or earlier. The recommended way to use them to check for "version 88 X.Y or later" is (eg) 89 90 #if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \ 91 && (__VALGRIND_MAJOR__ > 3 \ 92 || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6)) 93 */ 94 #define __VALGRIND_MAJOR__ 3 95 #define __VALGRIND_MINOR__ 6 96 97 98 #include <stdarg.h> 99 100 /* Nb: this file might be included in a file compiled with -ansi. So 101 we can't use C++ style "//" comments nor the "asm" keyword (instead 102 use "__asm__"). */ 103 104 /* Derive some tags indicating what the target platform is. Note 105 that in this file we're using the compiler's CPP symbols for 106 identifying architectures, which are different to the ones we use 107 within the rest of Valgrind. Note, __powerpc__ is active for both 108 32 and 64-bit PPC, whereas __powerpc64__ is only active for the 109 latter (on Linux, that is). 110 111 Misc note: how to find out what's predefined in gcc by default: 112 gcc -Wp,-dM somefile.c 113 */ 114 #undef PLAT_ppc64_aix5 115 #undef PLAT_ppc32_aix5 116 #undef PLAT_x86_darwin 117 #undef PLAT_amd64_darwin 118 #undef PLAT_x86_win32 119 #undef PLAT_x86_linux 120 #undef PLAT_amd64_linux 121 #undef PLAT_ppc32_linux 122 #undef PLAT_ppc64_linux 123 #undef PLAT_arm_linux 124 125 #if defined(_AIX) && defined(__64BIT__) 126 # define PLAT_ppc64_aix5 1 127 #elif defined(_AIX) && !defined(__64BIT__) 128 # define PLAT_ppc32_aix5 1 129 #elif defined(__APPLE__) && defined(__i386__) 130 # define PLAT_x86_darwin 1 131 #elif defined(__APPLE__) && defined(__x86_64__) 132 # define PLAT_amd64_darwin 1 133 #elif defined(__MINGW32__) || defined(__CYGWIN32__) || defined(_WIN32) && defined(_M_IX86) 134 # define PLAT_x86_win32 1 135 #elif defined(__linux__) && defined(__i386__) 136 # define PLAT_x86_linux 1 137 #elif defined(__linux__) && defined(__x86_64__) 138 # define PLAT_amd64_linux 1 139 #elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__) 140 # define PLAT_ppc32_linux 1 141 #elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) 142 # define PLAT_ppc64_linux 1 143 #elif defined(__linux__) && defined(__arm__) 144 # define PLAT_arm_linux 1 145 #else 146 /* If we're not compiling for our target platform, don't generate 147 any inline asms. */ 148 # if !defined(NVALGRIND) 149 # define NVALGRIND 1 150 # endif 151 #endif 152 153 154 /* ------------------------------------------------------------------ */ 155 /* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */ 156 /* in here of use to end-users -- skip to the next section. */ 157 /* ------------------------------------------------------------------ */ 158 159 #if defined(NVALGRIND) 160 161 /* Define NVALGRIND to completely remove the Valgrind magic sequence 162 from the compiled code (analogous to NDEBUG's effects on 163 assert()) */ 164 #define VALGRIND_DO_CLIENT_REQUEST( \ 165 _zzq_rlval, _zzq_default, _zzq_request, \ 166 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 167 { \ 168 (_zzq_rlval) = (_zzq_default); \ 169 } 170 171 #else /* ! NVALGRIND */ 172 173 /* The following defines the magic code sequences which the JITter 174 spots and handles magically. Don't look too closely at them as 175 they will rot your brain. 176 177 The assembly code sequences for all architectures is in this one 178 file. This is because this file must be stand-alone, and we don't 179 want to have multiple files. 180 181 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default 182 value gets put in the return slot, so that everything works when 183 this is executed not under Valgrind. Args are passed in a memory 184 block, and so there's no intrinsic limit to the number that could 185 be passed, but it's currently five. 186 187 The macro args are: 188 _zzq_rlval result lvalue 189 _zzq_default default value (result returned when running on real CPU) 190 _zzq_request request code 191 _zzq_arg1..5 request params 192 193 The other two macros are used to support function wrapping, and are 194 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the 195 guest's NRADDR pseudo-register and whatever other information is 196 needed to safely run the call original from the wrapper: on 197 ppc64-linux, the R2 value at the divert point is also needed. This 198 information is abstracted into a user-visible type, OrigFn. 199 200 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the 201 guest, but guarantees that the branch instruction will not be 202 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64: 203 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a 204 complete inline asm, since it needs to be combined with more magic 205 inline asm stuff to be useful. 206 */ 207 208 /* ------------------------- x86-{linux,darwin} ---------------- */ 209 210 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \ 211 || (defined(PLAT_x86_win32) && defined(__GNUC__)) 212 213 typedef 214 struct { 215 unsigned int nraddr; /* where's the code? */ 216 } 217 OrigFn; 218 219 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 220 "roll $3, %%edi ; roll $13, %%edi\n\t" \ 221 "roll $29, %%edi ; roll $19, %%edi\n\t" 222 223 #define VALGRIND_DO_CLIENT_REQUEST( \ 224 _zzq_rlval, _zzq_default, _zzq_request, \ 225 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 226 { volatile unsigned int _zzq_args[6]; \ 227 volatile unsigned int _zzq_result; \ 228 _zzq_args[0] = (unsigned int)(_zzq_request); \ 229 _zzq_args[1] = (unsigned int)(_zzq_arg1); \ 230 _zzq_args[2] = (unsigned int)(_zzq_arg2); \ 231 _zzq_args[3] = (unsigned int)(_zzq_arg3); \ 232 _zzq_args[4] = (unsigned int)(_zzq_arg4); \ 233 _zzq_args[5] = (unsigned int)(_zzq_arg5); \ 234 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 235 /* %EDX = client_request ( %EAX ) */ \ 236 "xchgl %%ebx,%%ebx" \ 237 : "=d" (_zzq_result) \ 238 : "a" (&_zzq_args[0]), "0" (_zzq_default) \ 239 : "cc", "memory" \ 240 ); \ 241 _zzq_rlval = _zzq_result; \ 242 } 243 244 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 245 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 246 volatile unsigned int __addr; \ 247 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 248 /* %EAX = guest_NRADDR */ \ 249 "xchgl %%ecx,%%ecx" \ 250 : "=a" (__addr) \ 251 : \ 252 : "cc", "memory" \ 253 ); \ 254 _zzq_orig->nraddr = __addr; \ 255 } 256 257 #define VALGRIND_CALL_NOREDIR_EAX \ 258 __SPECIAL_INSTRUCTION_PREAMBLE \ 259 /* call-noredir *%EAX */ \ 260 "xchgl %%edx,%%edx\n\t" 261 #endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__) */ 262 263 /* ------------------------- x86-Win32 ------------------------- */ 264 265 #if defined(PLAT_x86_win32) && !defined(__GNUC__) 266 267 typedef 268 struct { 269 unsigned int nraddr; /* where's the code? */ 270 } 271 OrigFn; 272 273 #if defined(_MSC_VER) 274 275 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 276 __asm rol edi, 3 __asm rol edi, 13 \ 277 __asm rol edi, 29 __asm rol edi, 19 278 279 #define VALGRIND_DO_CLIENT_REQUEST( \ 280 _zzq_rlval, _zzq_default, _zzq_request, \ 281 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 282 { volatile uintptr_t _zzq_args[6]; \ 283 volatile unsigned int _zzq_result; \ 284 _zzq_args[0] = (uintptr_t)(_zzq_request); \ 285 _zzq_args[1] = (uintptr_t)(_zzq_arg1); \ 286 _zzq_args[2] = (uintptr_t)(_zzq_arg2); \ 287 _zzq_args[3] = (uintptr_t)(_zzq_arg3); \ 288 _zzq_args[4] = (uintptr_t)(_zzq_arg4); \ 289 _zzq_args[5] = (uintptr_t)(_zzq_arg5); \ 290 __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default \ 291 __SPECIAL_INSTRUCTION_PREAMBLE \ 292 /* %EDX = client_request ( %EAX ) */ \ 293 __asm xchg ebx,ebx \ 294 __asm mov _zzq_result, edx \ 295 } \ 296 _zzq_rlval = _zzq_result; \ 297 } 298 299 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 300 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 301 volatile unsigned int __addr; \ 302 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \ 303 /* %EAX = guest_NRADDR */ \ 304 __asm xchg ecx,ecx \ 305 __asm mov __addr, eax \ 306 } \ 307 _zzq_orig->nraddr = __addr; \ 308 } 309 310 #define VALGRIND_CALL_NOREDIR_EAX ERROR 311 312 #else 313 #error Unsupported compiler. 314 #endif 315 316 #endif /* PLAT_x86_win32 */ 317 318 /* ------------------------ amd64-{linux,darwin} --------------- */ 319 320 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) 321 322 typedef 323 struct { 324 unsigned long long int nraddr; /* where's the code? */ 325 } 326 OrigFn; 327 328 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 329 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \ 330 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" 331 332 #define VALGRIND_DO_CLIENT_REQUEST( \ 333 _zzq_rlval, _zzq_default, _zzq_request, \ 334 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 335 { volatile unsigned long long int _zzq_args[6]; \ 336 volatile unsigned long long int _zzq_result; \ 337 _zzq_args[0] = (unsigned long long int)(_zzq_request); \ 338 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ 339 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ 340 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ 341 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ 342 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ 343 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 344 /* %RDX = client_request ( %RAX ) */ \ 345 "xchgq %%rbx,%%rbx" \ 346 : "=d" (_zzq_result) \ 347 : "a" (&_zzq_args[0]), "0" (_zzq_default) \ 348 : "cc", "memory" \ 349 ); \ 350 _zzq_rlval = _zzq_result; \ 351 } 352 353 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 354 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 355 volatile unsigned long long int __addr; \ 356 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 357 /* %RAX = guest_NRADDR */ \ 358 "xchgq %%rcx,%%rcx" \ 359 : "=a" (__addr) \ 360 : \ 361 : "cc", "memory" \ 362 ); \ 363 _zzq_orig->nraddr = __addr; \ 364 } 365 366 #define VALGRIND_CALL_NOREDIR_RAX \ 367 __SPECIAL_INSTRUCTION_PREAMBLE \ 368 /* call-noredir *%RAX */ \ 369 "xchgq %%rdx,%%rdx\n\t" 370 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin */ 371 372 /* ------------------------ ppc32-linux ------------------------ */ 373 374 #if defined(PLAT_ppc32_linux) 375 376 typedef 377 struct { 378 unsigned int nraddr; /* where's the code? */ 379 } 380 OrigFn; 381 382 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 383 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ 384 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" 385 386 #define VALGRIND_DO_CLIENT_REQUEST( \ 387 _zzq_rlval, _zzq_default, _zzq_request, \ 388 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 389 \ 390 { unsigned int _zzq_args[6]; \ 391 unsigned int _zzq_result; \ 392 unsigned int* _zzq_ptr; \ 393 _zzq_args[0] = (unsigned int)(_zzq_request); \ 394 _zzq_args[1] = (unsigned int)(_zzq_arg1); \ 395 _zzq_args[2] = (unsigned int)(_zzq_arg2); \ 396 _zzq_args[3] = (unsigned int)(_zzq_arg3); \ 397 _zzq_args[4] = (unsigned int)(_zzq_arg4); \ 398 _zzq_args[5] = (unsigned int)(_zzq_arg5); \ 399 _zzq_ptr = _zzq_args; \ 400 __asm__ volatile("mr 3,%1\n\t" /*default*/ \ 401 "mr 4,%2\n\t" /*ptr*/ \ 402 __SPECIAL_INSTRUCTION_PREAMBLE \ 403 /* %R3 = client_request ( %R4 ) */ \ 404 "or 1,1,1\n\t" \ 405 "mr %0,3" /*result*/ \ 406 : "=b" (_zzq_result) \ 407 : "b" (_zzq_default), "b" (_zzq_ptr) \ 408 : "cc", "memory", "r3", "r4"); \ 409 _zzq_rlval = _zzq_result; \ 410 } 411 412 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 413 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 414 unsigned int __addr; \ 415 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 416 /* %R3 = guest_NRADDR */ \ 417 "or 2,2,2\n\t" \ 418 "mr %0,3" \ 419 : "=b" (__addr) \ 420 : \ 421 : "cc", "memory", "r3" \ 422 ); \ 423 _zzq_orig->nraddr = __addr; \ 424 } 425 426 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 427 __SPECIAL_INSTRUCTION_PREAMBLE \ 428 /* branch-and-link-to-noredir *%R11 */ \ 429 "or 3,3,3\n\t" 430 #endif /* PLAT_ppc32_linux */ 431 432 /* ------------------------ ppc64-linux ------------------------ */ 433 434 #if defined(PLAT_ppc64_linux) 435 436 typedef 437 struct { 438 unsigned long long int nraddr; /* where's the code? */ 439 unsigned long long int r2; /* what tocptr do we need? */ 440 } 441 OrigFn; 442 443 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 444 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ 445 "rotldi 0,0,61 ; rotldi 0,0,51\n\t" 446 447 #define VALGRIND_DO_CLIENT_REQUEST( \ 448 _zzq_rlval, _zzq_default, _zzq_request, \ 449 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 450 \ 451 { unsigned long long int _zzq_args[6]; \ 452 register unsigned long long int _zzq_result __asm__("r3"); \ 453 register unsigned long long int* _zzq_ptr __asm__("r4"); \ 454 _zzq_args[0] = (unsigned long long int)(_zzq_request); \ 455 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ 456 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ 457 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ 458 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ 459 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ 460 _zzq_ptr = _zzq_args; \ 461 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 462 /* %R3 = client_request ( %R4 ) */ \ 463 "or 1,1,1" \ 464 : "=r" (_zzq_result) \ 465 : "0" (_zzq_default), "r" (_zzq_ptr) \ 466 : "cc", "memory"); \ 467 _zzq_rlval = _zzq_result; \ 468 } 469 470 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 471 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 472 register unsigned long long int __addr __asm__("r3"); \ 473 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 474 /* %R3 = guest_NRADDR */ \ 475 "or 2,2,2" \ 476 : "=r" (__addr) \ 477 : \ 478 : "cc", "memory" \ 479 ); \ 480 _zzq_orig->nraddr = __addr; \ 481 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 482 /* %R3 = guest_NRADDR_GPR2 */ \ 483 "or 4,4,4" \ 484 : "=r" (__addr) \ 485 : \ 486 : "cc", "memory" \ 487 ); \ 488 _zzq_orig->r2 = __addr; \ 489 } 490 491 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 492 __SPECIAL_INSTRUCTION_PREAMBLE \ 493 /* branch-and-link-to-noredir *%R11 */ \ 494 "or 3,3,3\n\t" 495 496 #endif /* PLAT_ppc64_linux */ 497 498 /* ------------------------- arm-linux ------------------------- */ 499 500 #if defined(PLAT_arm_linux) 501 502 typedef 503 struct { 504 unsigned int nraddr; /* where's the code? */ 505 } 506 OrigFn; 507 508 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 509 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \ 510 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t" 511 512 #define VALGRIND_DO_CLIENT_REQUEST( \ 513 _zzq_rlval, _zzq_default, _zzq_request, \ 514 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 515 \ 516 { volatile unsigned int _zzq_args[6]; \ 517 volatile unsigned int _zzq_result; \ 518 _zzq_args[0] = (unsigned int)(_zzq_request); \ 519 _zzq_args[1] = (unsigned int)(_zzq_arg1); \ 520 _zzq_args[2] = (unsigned int)(_zzq_arg2); \ 521 _zzq_args[3] = (unsigned int)(_zzq_arg3); \ 522 _zzq_args[4] = (unsigned int)(_zzq_arg4); \ 523 _zzq_args[5] = (unsigned int)(_zzq_arg5); \ 524 __asm__ volatile("mov r3, %1\n\t" /*default*/ \ 525 "mov r4, %2\n\t" /*ptr*/ \ 526 __SPECIAL_INSTRUCTION_PREAMBLE \ 527 /* R3 = client_request ( R4 ) */ \ 528 "orr r10, r10, r10\n\t" \ 529 "mov %0, r3" /*result*/ \ 530 : "=r" (_zzq_result) \ 531 : "r" (_zzq_default), "r" (&_zzq_args[0]) \ 532 : "cc","memory", "r3", "r4"); \ 533 _zzq_rlval = _zzq_result; \ 534 } 535 536 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 537 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 538 unsigned int __addr; \ 539 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 540 /* R3 = guest_NRADDR */ \ 541 "orr r11, r11, r11\n\t" \ 542 "mov %0, r3" \ 543 : "=r" (__addr) \ 544 : \ 545 : "cc", "memory", "r3" \ 546 ); \ 547 _zzq_orig->nraddr = __addr; \ 548 } 549 550 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 551 __SPECIAL_INSTRUCTION_PREAMBLE \ 552 /* branch-and-link-to-noredir *%R4 */ \ 553 "orr r12, r12, r12\n\t" 554 555 #endif /* PLAT_arm_linux */ 556 557 /* ------------------------ ppc32-aix5 ------------------------- */ 558 559 #if defined(PLAT_ppc32_aix5) 560 561 typedef 562 struct { 563 unsigned int nraddr; /* where's the code? */ 564 unsigned int r2; /* what tocptr do we need? */ 565 } 566 OrigFn; 567 568 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 569 "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ 570 "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" 571 572 #define VALGRIND_DO_CLIENT_REQUEST( \ 573 _zzq_rlval, _zzq_default, _zzq_request, \ 574 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 575 \ 576 { unsigned int _zzq_args[7]; \ 577 register unsigned int _zzq_result; \ 578 register unsigned int* _zzq_ptr; \ 579 _zzq_args[0] = (unsigned int)(_zzq_request); \ 580 _zzq_args[1] = (unsigned int)(_zzq_arg1); \ 581 _zzq_args[2] = (unsigned int)(_zzq_arg2); \ 582 _zzq_args[3] = (unsigned int)(_zzq_arg3); \ 583 _zzq_args[4] = (unsigned int)(_zzq_arg4); \ 584 _zzq_args[5] = (unsigned int)(_zzq_arg5); \ 585 _zzq_args[6] = (unsigned int)(_zzq_default); \ 586 _zzq_ptr = _zzq_args; \ 587 __asm__ volatile("mr 4,%1\n\t" \ 588 "lwz 3, 24(4)\n\t" \ 589 __SPECIAL_INSTRUCTION_PREAMBLE \ 590 /* %R3 = client_request ( %R4 ) */ \ 591 "or 1,1,1\n\t" \ 592 "mr %0,3" \ 593 : "=b" (_zzq_result) \ 594 : "b" (_zzq_ptr) \ 595 : "r3", "r4", "cc", "memory"); \ 596 _zzq_rlval = _zzq_result; \ 597 } 598 599 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 600 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 601 register unsigned int __addr; \ 602 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 603 /* %R3 = guest_NRADDR */ \ 604 "or 2,2,2\n\t" \ 605 "mr %0,3" \ 606 : "=b" (__addr) \ 607 : \ 608 : "r3", "cc", "memory" \ 609 ); \ 610 _zzq_orig->nraddr = __addr; \ 611 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 612 /* %R3 = guest_NRADDR_GPR2 */ \ 613 "or 4,4,4\n\t" \ 614 "mr %0,3" \ 615 : "=b" (__addr) \ 616 : \ 617 : "r3", "cc", "memory" \ 618 ); \ 619 _zzq_orig->r2 = __addr; \ 620 } 621 622 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 623 __SPECIAL_INSTRUCTION_PREAMBLE \ 624 /* branch-and-link-to-noredir *%R11 */ \ 625 "or 3,3,3\n\t" 626 627 #endif /* PLAT_ppc32_aix5 */ 628 629 /* ------------------------ ppc64-aix5 ------------------------- */ 630 631 #if defined(PLAT_ppc64_aix5) 632 633 typedef 634 struct { 635 unsigned long long int nraddr; /* where's the code? */ 636 unsigned long long int r2; /* what tocptr do we need? */ 637 } 638 OrigFn; 639 640 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 641 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ 642 "rotldi 0,0,61 ; rotldi 0,0,51\n\t" 643 644 #define VALGRIND_DO_CLIENT_REQUEST( \ 645 _zzq_rlval, _zzq_default, _zzq_request, \ 646 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 647 \ 648 { unsigned long long int _zzq_args[7]; \ 649 register unsigned long long int _zzq_result; \ 650 register unsigned long long int* _zzq_ptr; \ 651 _zzq_args[0] = (unsigned int long long)(_zzq_request); \ 652 _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \ 653 _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \ 654 _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \ 655 _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \ 656 _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \ 657 _zzq_args[6] = (unsigned int long long)(_zzq_default); \ 658 _zzq_ptr = _zzq_args; \ 659 __asm__ volatile("mr 4,%1\n\t" \ 660 "ld 3, 48(4)\n\t" \ 661 __SPECIAL_INSTRUCTION_PREAMBLE \ 662 /* %R3 = client_request ( %R4 ) */ \ 663 "or 1,1,1\n\t" \ 664 "mr %0,3" \ 665 : "=b" (_zzq_result) \ 666 : "b" (_zzq_ptr) \ 667 : "r3", "r4", "cc", "memory"); \ 668 _zzq_rlval = _zzq_result; \ 669 } 670 671 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 672 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 673 register unsigned long long int __addr; \ 674 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 675 /* %R3 = guest_NRADDR */ \ 676 "or 2,2,2\n\t" \ 677 "mr %0,3" \ 678 : "=b" (__addr) \ 679 : \ 680 : "r3", "cc", "memory" \ 681 ); \ 682 _zzq_orig->nraddr = __addr; \ 683 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 684 /* %R3 = guest_NRADDR_GPR2 */ \ 685 "or 4,4,4\n\t" \ 686 "mr %0,3" \ 687 : "=b" (__addr) \ 688 : \ 689 : "r3", "cc", "memory" \ 690 ); \ 691 _zzq_orig->r2 = __addr; \ 692 } 693 694 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 695 __SPECIAL_INSTRUCTION_PREAMBLE \ 696 /* branch-and-link-to-noredir *%R11 */ \ 697 "or 3,3,3\n\t" 698 699 #endif /* PLAT_ppc64_aix5 */ 700 701 /* Insert assembly code for other platforms here... */ 702 703 #endif /* NVALGRIND */ 704 705 706 /* ------------------------------------------------------------------ */ 707 /* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */ 708 /* ugly. It's the least-worst tradeoff I can think of. */ 709 /* ------------------------------------------------------------------ */ 710 711 /* This section defines magic (a.k.a appalling-hack) macros for doing 712 guaranteed-no-redirection macros, so as to get from function 713 wrappers to the functions they are wrapping. The whole point is to 714 construct standard call sequences, but to do the call itself with a 715 special no-redirect call pseudo-instruction that the JIT 716 understands and handles specially. This section is long and 717 repetitious, and I can't see a way to make it shorter. 718 719 The naming scheme is as follows: 720 721 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc} 722 723 'W' stands for "word" and 'v' for "void". Hence there are 724 different macros for calling arity 0, 1, 2, 3, 4, etc, functions, 725 and for each, the possibility of returning a word-typed result, or 726 no result. 727 */ 728 729 /* Use these to write the name of your wrapper. NOTE: duplicates 730 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */ 731 732 /* Use an extra level of macroisation so as to ensure the soname/fnname 733 args are fully macro-expanded before pasting them together. */ 734 #define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd 735 736 #define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \ 737 VG_CONCAT4(_vgwZU_,soname,_,fnname) 738 739 #define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \ 740 VG_CONCAT4(_vgwZZ_,soname,_,fnname) 741 742 /* Use this macro from within a wrapper function to collect the 743 context (address and possibly other info) of the original function. 744 Once you have that you can then use it in one of the CALL_FN_ 745 macros. The type of the argument _lval is OrigFn. */ 746 #define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval) 747 748 /* Derivatives of the main macros below, for calling functions 749 returning void. */ 750 751 #define CALL_FN_v_v(fnptr) \ 752 do { volatile unsigned long _junk; \ 753 CALL_FN_W_v(_junk,fnptr); } while (0) 754 755 #define CALL_FN_v_W(fnptr, arg1) \ 756 do { volatile unsigned long _junk; \ 757 CALL_FN_W_W(_junk,fnptr,arg1); } while (0) 758 759 #define CALL_FN_v_WW(fnptr, arg1,arg2) \ 760 do { volatile unsigned long _junk; \ 761 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0) 762 763 #define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \ 764 do { volatile unsigned long _junk; \ 765 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0) 766 767 #define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \ 768 do { volatile unsigned long _junk; \ 769 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0) 770 771 #define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \ 772 do { volatile unsigned long _junk; \ 773 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0) 774 775 #define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \ 776 do { volatile unsigned long _junk; \ 777 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0) 778 779 #define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \ 780 do { volatile unsigned long _junk; \ 781 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0) 782 783 /* ------------------------- x86-{linux,darwin} ---------------- */ 784 785 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) 786 787 /* These regs are trashed by the hidden call. No need to mention eax 788 as gcc can already see that, plus causes gcc to bomb. */ 789 #define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx" 790 791 /* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned 792 long) == 4. */ 793 794 #define CALL_FN_W_v(lval, orig) \ 795 do { \ 796 volatile OrigFn _orig = (orig); \ 797 volatile unsigned long _argvec[1]; \ 798 volatile unsigned long _res; \ 799 _argvec[0] = (unsigned long)_orig.nraddr; \ 800 __asm__ volatile( \ 801 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 802 VALGRIND_CALL_NOREDIR_EAX \ 803 : /*out*/ "=a" (_res) \ 804 : /*in*/ "a" (&_argvec[0]) \ 805 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 806 ); \ 807 lval = (__typeof__(lval)) _res; \ 808 } while (0) 809 810 #define CALL_FN_W_W(lval, orig, arg1) \ 811 do { \ 812 volatile OrigFn _orig = (orig); \ 813 volatile unsigned long _argvec[2]; \ 814 volatile unsigned long _res; \ 815 _argvec[0] = (unsigned long)_orig.nraddr; \ 816 _argvec[1] = (unsigned long)(arg1); \ 817 __asm__ volatile( \ 818 "subl $12, %%esp\n\t" \ 819 "pushl 4(%%eax)\n\t" \ 820 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 821 VALGRIND_CALL_NOREDIR_EAX \ 822 "addl $16, %%esp\n" \ 823 : /*out*/ "=a" (_res) \ 824 : /*in*/ "a" (&_argvec[0]) \ 825 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 826 ); \ 827 lval = (__typeof__(lval)) _res; \ 828 } while (0) 829 830 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 831 do { \ 832 volatile OrigFn _orig = (orig); \ 833 volatile unsigned long _argvec[3]; \ 834 volatile unsigned long _res; \ 835 _argvec[0] = (unsigned long)_orig.nraddr; \ 836 _argvec[1] = (unsigned long)(arg1); \ 837 _argvec[2] = (unsigned long)(arg2); \ 838 __asm__ volatile( \ 839 "subl $8, %%esp\n\t" \ 840 "pushl 8(%%eax)\n\t" \ 841 "pushl 4(%%eax)\n\t" \ 842 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 843 VALGRIND_CALL_NOREDIR_EAX \ 844 "addl $16, %%esp\n" \ 845 : /*out*/ "=a" (_res) \ 846 : /*in*/ "a" (&_argvec[0]) \ 847 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 848 ); \ 849 lval = (__typeof__(lval)) _res; \ 850 } while (0) 851 852 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 853 do { \ 854 volatile OrigFn _orig = (orig); \ 855 volatile unsigned long _argvec[4]; \ 856 volatile unsigned long _res; \ 857 _argvec[0] = (unsigned long)_orig.nraddr; \ 858 _argvec[1] = (unsigned long)(arg1); \ 859 _argvec[2] = (unsigned long)(arg2); \ 860 _argvec[3] = (unsigned long)(arg3); \ 861 __asm__ volatile( \ 862 "subl $4, %%esp\n\t" \ 863 "pushl 12(%%eax)\n\t" \ 864 "pushl 8(%%eax)\n\t" \ 865 "pushl 4(%%eax)\n\t" \ 866 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 867 VALGRIND_CALL_NOREDIR_EAX \ 868 "addl $16, %%esp\n" \ 869 : /*out*/ "=a" (_res) \ 870 : /*in*/ "a" (&_argvec[0]) \ 871 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 872 ); \ 873 lval = (__typeof__(lval)) _res; \ 874 } while (0) 875 876 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 877 do { \ 878 volatile OrigFn _orig = (orig); \ 879 volatile unsigned long _argvec[5]; \ 880 volatile unsigned long _res; \ 881 _argvec[0] = (unsigned long)_orig.nraddr; \ 882 _argvec[1] = (unsigned long)(arg1); \ 883 _argvec[2] = (unsigned long)(arg2); \ 884 _argvec[3] = (unsigned long)(arg3); \ 885 _argvec[4] = (unsigned long)(arg4); \ 886 __asm__ volatile( \ 887 "pushl 16(%%eax)\n\t" \ 888 "pushl 12(%%eax)\n\t" \ 889 "pushl 8(%%eax)\n\t" \ 890 "pushl 4(%%eax)\n\t" \ 891 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 892 VALGRIND_CALL_NOREDIR_EAX \ 893 "addl $16, %%esp\n" \ 894 : /*out*/ "=a" (_res) \ 895 : /*in*/ "a" (&_argvec[0]) \ 896 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 897 ); \ 898 lval = (__typeof__(lval)) _res; \ 899 } while (0) 900 901 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 902 do { \ 903 volatile OrigFn _orig = (orig); \ 904 volatile unsigned long _argvec[6]; \ 905 volatile unsigned long _res; \ 906 _argvec[0] = (unsigned long)_orig.nraddr; \ 907 _argvec[1] = (unsigned long)(arg1); \ 908 _argvec[2] = (unsigned long)(arg2); \ 909 _argvec[3] = (unsigned long)(arg3); \ 910 _argvec[4] = (unsigned long)(arg4); \ 911 _argvec[5] = (unsigned long)(arg5); \ 912 __asm__ volatile( \ 913 "subl $12, %%esp\n\t" \ 914 "pushl 20(%%eax)\n\t" \ 915 "pushl 16(%%eax)\n\t" \ 916 "pushl 12(%%eax)\n\t" \ 917 "pushl 8(%%eax)\n\t" \ 918 "pushl 4(%%eax)\n\t" \ 919 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 920 VALGRIND_CALL_NOREDIR_EAX \ 921 "addl $32, %%esp\n" \ 922 : /*out*/ "=a" (_res) \ 923 : /*in*/ "a" (&_argvec[0]) \ 924 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 925 ); \ 926 lval = (__typeof__(lval)) _res; \ 927 } while (0) 928 929 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 930 do { \ 931 volatile OrigFn _orig = (orig); \ 932 volatile unsigned long _argvec[7]; \ 933 volatile unsigned long _res; \ 934 _argvec[0] = (unsigned long)_orig.nraddr; \ 935 _argvec[1] = (unsigned long)(arg1); \ 936 _argvec[2] = (unsigned long)(arg2); \ 937 _argvec[3] = (unsigned long)(arg3); \ 938 _argvec[4] = (unsigned long)(arg4); \ 939 _argvec[5] = (unsigned long)(arg5); \ 940 _argvec[6] = (unsigned long)(arg6); \ 941 __asm__ volatile( \ 942 "subl $8, %%esp\n\t" \ 943 "pushl 24(%%eax)\n\t" \ 944 "pushl 20(%%eax)\n\t" \ 945 "pushl 16(%%eax)\n\t" \ 946 "pushl 12(%%eax)\n\t" \ 947 "pushl 8(%%eax)\n\t" \ 948 "pushl 4(%%eax)\n\t" \ 949 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 950 VALGRIND_CALL_NOREDIR_EAX \ 951 "addl $32, %%esp\n" \ 952 : /*out*/ "=a" (_res) \ 953 : /*in*/ "a" (&_argvec[0]) \ 954 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 955 ); \ 956 lval = (__typeof__(lval)) _res; \ 957 } while (0) 958 959 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 960 arg7) \ 961 do { \ 962 volatile OrigFn _orig = (orig); \ 963 volatile unsigned long _argvec[8]; \ 964 volatile unsigned long _res; \ 965 _argvec[0] = (unsigned long)_orig.nraddr; \ 966 _argvec[1] = (unsigned long)(arg1); \ 967 _argvec[2] = (unsigned long)(arg2); \ 968 _argvec[3] = (unsigned long)(arg3); \ 969 _argvec[4] = (unsigned long)(arg4); \ 970 _argvec[5] = (unsigned long)(arg5); \ 971 _argvec[6] = (unsigned long)(arg6); \ 972 _argvec[7] = (unsigned long)(arg7); \ 973 __asm__ volatile( \ 974 "subl $4, %%esp\n\t" \ 975 "pushl 28(%%eax)\n\t" \ 976 "pushl 24(%%eax)\n\t" \ 977 "pushl 20(%%eax)\n\t" \ 978 "pushl 16(%%eax)\n\t" \ 979 "pushl 12(%%eax)\n\t" \ 980 "pushl 8(%%eax)\n\t" \ 981 "pushl 4(%%eax)\n\t" \ 982 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 983 VALGRIND_CALL_NOREDIR_EAX \ 984 "addl $32, %%esp\n" \ 985 : /*out*/ "=a" (_res) \ 986 : /*in*/ "a" (&_argvec[0]) \ 987 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 988 ); \ 989 lval = (__typeof__(lval)) _res; \ 990 } while (0) 991 992 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 993 arg7,arg8) \ 994 do { \ 995 volatile OrigFn _orig = (orig); \ 996 volatile unsigned long _argvec[9]; \ 997 volatile unsigned long _res; \ 998 _argvec[0] = (unsigned long)_orig.nraddr; \ 999 _argvec[1] = (unsigned long)(arg1); \ 1000 _argvec[2] = (unsigned long)(arg2); \ 1001 _argvec[3] = (unsigned long)(arg3); \ 1002 _argvec[4] = (unsigned long)(arg4); \ 1003 _argvec[5] = (unsigned long)(arg5); \ 1004 _argvec[6] = (unsigned long)(arg6); \ 1005 _argvec[7] = (unsigned long)(arg7); \ 1006 _argvec[8] = (unsigned long)(arg8); \ 1007 __asm__ volatile( \ 1008 "pushl 32(%%eax)\n\t" \ 1009 "pushl 28(%%eax)\n\t" \ 1010 "pushl 24(%%eax)\n\t" \ 1011 "pushl 20(%%eax)\n\t" \ 1012 "pushl 16(%%eax)\n\t" \ 1013 "pushl 12(%%eax)\n\t" \ 1014 "pushl 8(%%eax)\n\t" \ 1015 "pushl 4(%%eax)\n\t" \ 1016 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1017 VALGRIND_CALL_NOREDIR_EAX \ 1018 "addl $32, %%esp\n" \ 1019 : /*out*/ "=a" (_res) \ 1020 : /*in*/ "a" (&_argvec[0]) \ 1021 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1022 ); \ 1023 lval = (__typeof__(lval)) _res; \ 1024 } while (0) 1025 1026 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1027 arg7,arg8,arg9) \ 1028 do { \ 1029 volatile OrigFn _orig = (orig); \ 1030 volatile unsigned long _argvec[10]; \ 1031 volatile unsigned long _res; \ 1032 _argvec[0] = (unsigned long)_orig.nraddr; \ 1033 _argvec[1] = (unsigned long)(arg1); \ 1034 _argvec[2] = (unsigned long)(arg2); \ 1035 _argvec[3] = (unsigned long)(arg3); \ 1036 _argvec[4] = (unsigned long)(arg4); \ 1037 _argvec[5] = (unsigned long)(arg5); \ 1038 _argvec[6] = (unsigned long)(arg6); \ 1039 _argvec[7] = (unsigned long)(arg7); \ 1040 _argvec[8] = (unsigned long)(arg8); \ 1041 _argvec[9] = (unsigned long)(arg9); \ 1042 __asm__ volatile( \ 1043 "subl $12, %%esp\n\t" \ 1044 "pushl 36(%%eax)\n\t" \ 1045 "pushl 32(%%eax)\n\t" \ 1046 "pushl 28(%%eax)\n\t" \ 1047 "pushl 24(%%eax)\n\t" \ 1048 "pushl 20(%%eax)\n\t" \ 1049 "pushl 16(%%eax)\n\t" \ 1050 "pushl 12(%%eax)\n\t" \ 1051 "pushl 8(%%eax)\n\t" \ 1052 "pushl 4(%%eax)\n\t" \ 1053 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1054 VALGRIND_CALL_NOREDIR_EAX \ 1055 "addl $48, %%esp\n" \ 1056 : /*out*/ "=a" (_res) \ 1057 : /*in*/ "a" (&_argvec[0]) \ 1058 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1059 ); \ 1060 lval = (__typeof__(lval)) _res; \ 1061 } while (0) 1062 1063 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1064 arg7,arg8,arg9,arg10) \ 1065 do { \ 1066 volatile OrigFn _orig = (orig); \ 1067 volatile unsigned long _argvec[11]; \ 1068 volatile unsigned long _res; \ 1069 _argvec[0] = (unsigned long)_orig.nraddr; \ 1070 _argvec[1] = (unsigned long)(arg1); \ 1071 _argvec[2] = (unsigned long)(arg2); \ 1072 _argvec[3] = (unsigned long)(arg3); \ 1073 _argvec[4] = (unsigned long)(arg4); \ 1074 _argvec[5] = (unsigned long)(arg5); \ 1075 _argvec[6] = (unsigned long)(arg6); \ 1076 _argvec[7] = (unsigned long)(arg7); \ 1077 _argvec[8] = (unsigned long)(arg8); \ 1078 _argvec[9] = (unsigned long)(arg9); \ 1079 _argvec[10] = (unsigned long)(arg10); \ 1080 __asm__ volatile( \ 1081 "subl $8, %%esp\n\t" \ 1082 "pushl 40(%%eax)\n\t" \ 1083 "pushl 36(%%eax)\n\t" \ 1084 "pushl 32(%%eax)\n\t" \ 1085 "pushl 28(%%eax)\n\t" \ 1086 "pushl 24(%%eax)\n\t" \ 1087 "pushl 20(%%eax)\n\t" \ 1088 "pushl 16(%%eax)\n\t" \ 1089 "pushl 12(%%eax)\n\t" \ 1090 "pushl 8(%%eax)\n\t" \ 1091 "pushl 4(%%eax)\n\t" \ 1092 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1093 VALGRIND_CALL_NOREDIR_EAX \ 1094 "addl $48, %%esp\n" \ 1095 : /*out*/ "=a" (_res) \ 1096 : /*in*/ "a" (&_argvec[0]) \ 1097 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1098 ); \ 1099 lval = (__typeof__(lval)) _res; \ 1100 } while (0) 1101 1102 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ 1103 arg6,arg7,arg8,arg9,arg10, \ 1104 arg11) \ 1105 do { \ 1106 volatile OrigFn _orig = (orig); \ 1107 volatile unsigned long _argvec[12]; \ 1108 volatile unsigned long _res; \ 1109 _argvec[0] = (unsigned long)_orig.nraddr; \ 1110 _argvec[1] = (unsigned long)(arg1); \ 1111 _argvec[2] = (unsigned long)(arg2); \ 1112 _argvec[3] = (unsigned long)(arg3); \ 1113 _argvec[4] = (unsigned long)(arg4); \ 1114 _argvec[5] = (unsigned long)(arg5); \ 1115 _argvec[6] = (unsigned long)(arg6); \ 1116 _argvec[7] = (unsigned long)(arg7); \ 1117 _argvec[8] = (unsigned long)(arg8); \ 1118 _argvec[9] = (unsigned long)(arg9); \ 1119 _argvec[10] = (unsigned long)(arg10); \ 1120 _argvec[11] = (unsigned long)(arg11); \ 1121 __asm__ volatile( \ 1122 "subl $4, %%esp\n\t" \ 1123 "pushl 44(%%eax)\n\t" \ 1124 "pushl 40(%%eax)\n\t" \ 1125 "pushl 36(%%eax)\n\t" \ 1126 "pushl 32(%%eax)\n\t" \ 1127 "pushl 28(%%eax)\n\t" \ 1128 "pushl 24(%%eax)\n\t" \ 1129 "pushl 20(%%eax)\n\t" \ 1130 "pushl 16(%%eax)\n\t" \ 1131 "pushl 12(%%eax)\n\t" \ 1132 "pushl 8(%%eax)\n\t" \ 1133 "pushl 4(%%eax)\n\t" \ 1134 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1135 VALGRIND_CALL_NOREDIR_EAX \ 1136 "addl $48, %%esp\n" \ 1137 : /*out*/ "=a" (_res) \ 1138 : /*in*/ "a" (&_argvec[0]) \ 1139 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1140 ); \ 1141 lval = (__typeof__(lval)) _res; \ 1142 } while (0) 1143 1144 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ 1145 arg6,arg7,arg8,arg9,arg10, \ 1146 arg11,arg12) \ 1147 do { \ 1148 volatile OrigFn _orig = (orig); \ 1149 volatile unsigned long _argvec[13]; \ 1150 volatile unsigned long _res; \ 1151 _argvec[0] = (unsigned long)_orig.nraddr; \ 1152 _argvec[1] = (unsigned long)(arg1); \ 1153 _argvec[2] = (unsigned long)(arg2); \ 1154 _argvec[3] = (unsigned long)(arg3); \ 1155 _argvec[4] = (unsigned long)(arg4); \ 1156 _argvec[5] = (unsigned long)(arg5); \ 1157 _argvec[6] = (unsigned long)(arg6); \ 1158 _argvec[7] = (unsigned long)(arg7); \ 1159 _argvec[8] = (unsigned long)(arg8); \ 1160 _argvec[9] = (unsigned long)(arg9); \ 1161 _argvec[10] = (unsigned long)(arg10); \ 1162 _argvec[11] = (unsigned long)(arg11); \ 1163 _argvec[12] = (unsigned long)(arg12); \ 1164 __asm__ volatile( \ 1165 "pushl 48(%%eax)\n\t" \ 1166 "pushl 44(%%eax)\n\t" \ 1167 "pushl 40(%%eax)\n\t" \ 1168 "pushl 36(%%eax)\n\t" \ 1169 "pushl 32(%%eax)\n\t" \ 1170 "pushl 28(%%eax)\n\t" \ 1171 "pushl 24(%%eax)\n\t" \ 1172 "pushl 20(%%eax)\n\t" \ 1173 "pushl 16(%%eax)\n\t" \ 1174 "pushl 12(%%eax)\n\t" \ 1175 "pushl 8(%%eax)\n\t" \ 1176 "pushl 4(%%eax)\n\t" \ 1177 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1178 VALGRIND_CALL_NOREDIR_EAX \ 1179 "addl $48, %%esp\n" \ 1180 : /*out*/ "=a" (_res) \ 1181 : /*in*/ "a" (&_argvec[0]) \ 1182 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1183 ); \ 1184 lval = (__typeof__(lval)) _res; \ 1185 } while (0) 1186 1187 #endif /* PLAT_x86_linux || PLAT_x86_darwin */ 1188 1189 /* ------------------------ amd64-{linux,darwin} --------------- */ 1190 1191 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) 1192 1193 /* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */ 1194 1195 /* These regs are trashed by the hidden call. */ 1196 #define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \ 1197 "rdi", "r8", "r9", "r10", "r11" 1198 1199 /* This is all pretty complex. It's so as to make stack unwinding 1200 work reliably. See bug 243270. The basic problem is the sub and 1201 add of 128 of %rsp in all of the following macros. If gcc believes 1202 the CFA is in %rsp, then unwinding may fail, because what's at the 1203 CFA is not what gcc "expected" when it constructs the CFIs for the 1204 places where the macros are instantiated. 1205 1206 But we can't just add a CFI annotation to increase the CFA offset 1207 by 128, to match the sub of 128 from %rsp, because we don't know 1208 whether gcc has chosen %rsp as the CFA at that point, or whether it 1209 has chosen some other register (eg, %rbp). In the latter case, 1210 adding a CFI annotation to change the CFA offset is simply wrong. 1211 1212 So the solution is to get hold of the CFA using 1213 __builtin_dwarf_cfa(), put it in a known register, and add a 1214 CFI annotation to say what the register is. We choose %rbp for 1215 this (perhaps perversely), because: 1216 1217 (1) %rbp is already subject to unwinding. If a new register was 1218 chosen then the unwinder would have to unwind it in all stack 1219 traces, which is expensive, and 1220 1221 (2) %rbp is already subject to precise exception updates in the 1222 JIT. If a new register was chosen, we'd have to have precise 1223 exceptions for it too, which reduces performance of the 1224 generated code. 1225 1226 However .. one extra complication. We can't just whack the result 1227 of __builtin_dwarf_cfa() into %rbp and then add %rbp to the 1228 list of trashed registers at the end of the inline assembly 1229 fragments; gcc won't allow %rbp to appear in that list. Hence 1230 instead we need to stash %rbp in %r15 for the duration of the asm, 1231 and say that %r15 is trashed instead. gcc seems happy to go with 1232 that. 1233 1234 Oh .. and this all needs to be conditionalised so that it is 1235 unchanged from before this commit, when compiled with older gccs 1236 that don't support __builtin_dwarf_cfa. Furthermore, since 1237 this header file is freestanding, it has to be independent of 1238 config.h, and so the following conditionalisation cannot depend on 1239 configure time checks. 1240 1241 Although it's not clear from 1242 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)', 1243 this expression excludes Darwin. 1244 .cfi directives in Darwin assembly appear to be completely 1245 different and I haven't investigated how they work. 1246 1247 For even more entertainment value, note we have to use the 1248 completely undocumented __builtin_dwarf_cfa(), which appears to 1249 really compute the CFA, whereas __builtin_frame_address(0) claims 1250 to but actually doesn't. See 1251 https://bugs.kde.org/show_bug.cgi?id=243270#c47 1252 */ 1253 #if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM) 1254 # define __FRAME_POINTER \ 1255 ,"r"(__builtin_dwarf_cfa()) 1256 # define VALGRIND_CFI_PROLOGUE \ 1257 "movq %%rbp, %%r15\n\t" \ 1258 "movq %2, %%rbp\n\t" \ 1259 ".cfi_remember_state\n\t" \ 1260 ".cfi_def_cfa rbp, 0\n\t" 1261 # define VALGRIND_CFI_EPILOGUE \ 1262 "movq %%r15, %%rbp\n\t" \ 1263 ".cfi_restore_state\n\t" 1264 #else 1265 # define __FRAME_POINTER 1266 # define VALGRIND_CFI_PROLOGUE 1267 # define VALGRIND_CFI_EPILOGUE 1268 #endif 1269 1270 1271 /* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned 1272 long) == 8. */ 1273 1274 /* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_ 1275 macros. In order not to trash the stack redzone, we need to drop 1276 %rsp by 128 before the hidden call, and restore afterwards. The 1277 nastyness is that it is only by luck that the stack still appears 1278 to be unwindable during the hidden call - since then the behaviour 1279 of any routine using this macro does not match what the CFI data 1280 says. Sigh. 1281 1282 Why is this important? Imagine that a wrapper has a stack 1283 allocated local, and passes to the hidden call, a pointer to it. 1284 Because gcc does not know about the hidden call, it may allocate 1285 that local in the redzone. Unfortunately the hidden call may then 1286 trash it before it comes to use it. So we must step clear of the 1287 redzone, for the duration of the hidden call, to make it safe. 1288 1289 Probably the same problem afflicts the other redzone-style ABIs too 1290 (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is 1291 self describing (none of this CFI nonsense) so at least messing 1292 with the stack pointer doesn't give a danger of non-unwindable 1293 stack. */ 1294 1295 #define CALL_FN_W_v(lval, orig) \ 1296 do { \ 1297 volatile OrigFn _orig = (orig); \ 1298 volatile unsigned long _argvec[1]; \ 1299 volatile unsigned long _res; \ 1300 _argvec[0] = (unsigned long)_orig.nraddr; \ 1301 __asm__ volatile( \ 1302 VALGRIND_CFI_PROLOGUE \ 1303 "subq $128,%%rsp\n\t" \ 1304 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1305 VALGRIND_CALL_NOREDIR_RAX \ 1306 "addq $128,%%rsp\n\t" \ 1307 VALGRIND_CFI_EPILOGUE \ 1308 : /*out*/ "=a" (_res) \ 1309 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1310 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ 1311 ); \ 1312 lval = (__typeof__(lval)) _res; \ 1313 } while (0) 1314 1315 #define CALL_FN_W_W(lval, orig, arg1) \ 1316 do { \ 1317 volatile OrigFn _orig = (orig); \ 1318 volatile unsigned long _argvec[2]; \ 1319 volatile unsigned long _res; \ 1320 _argvec[0] = (unsigned long)_orig.nraddr; \ 1321 _argvec[1] = (unsigned long)(arg1); \ 1322 __asm__ volatile( \ 1323 VALGRIND_CFI_PROLOGUE \ 1324 "subq $128,%%rsp\n\t" \ 1325 "movq 8(%%rax), %%rdi\n\t" \ 1326 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1327 VALGRIND_CALL_NOREDIR_RAX \ 1328 "addq $128,%%rsp\n\t" \ 1329 VALGRIND_CFI_EPILOGUE \ 1330 : /*out*/ "=a" (_res) \ 1331 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1332 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ 1333 ); \ 1334 lval = (__typeof__(lval)) _res; \ 1335 } while (0) 1336 1337 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 1338 do { \ 1339 volatile OrigFn _orig = (orig); \ 1340 volatile unsigned long _argvec[3]; \ 1341 volatile unsigned long _res; \ 1342 _argvec[0] = (unsigned long)_orig.nraddr; \ 1343 _argvec[1] = (unsigned long)(arg1); \ 1344 _argvec[2] = (unsigned long)(arg2); \ 1345 __asm__ volatile( \ 1346 VALGRIND_CFI_PROLOGUE \ 1347 "subq $128,%%rsp\n\t" \ 1348 "movq 16(%%rax), %%rsi\n\t" \ 1349 "movq 8(%%rax), %%rdi\n\t" \ 1350 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1351 VALGRIND_CALL_NOREDIR_RAX \ 1352 "addq $128,%%rsp\n\t" \ 1353 VALGRIND_CFI_EPILOGUE \ 1354 : /*out*/ "=a" (_res) \ 1355 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1356 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ 1357 ); \ 1358 lval = (__typeof__(lval)) _res; \ 1359 } while (0) 1360 1361 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 1362 do { \ 1363 volatile OrigFn _orig = (orig); \ 1364 volatile unsigned long _argvec[4]; \ 1365 volatile unsigned long _res; \ 1366 _argvec[0] = (unsigned long)_orig.nraddr; \ 1367 _argvec[1] = (unsigned long)(arg1); \ 1368 _argvec[2] = (unsigned long)(arg2); \ 1369 _argvec[3] = (unsigned long)(arg3); \ 1370 __asm__ volatile( \ 1371 VALGRIND_CFI_PROLOGUE \ 1372 "subq $128,%%rsp\n\t" \ 1373 "movq 24(%%rax), %%rdx\n\t" \ 1374 "movq 16(%%rax), %%rsi\n\t" \ 1375 "movq 8(%%rax), %%rdi\n\t" \ 1376 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1377 VALGRIND_CALL_NOREDIR_RAX \ 1378 "addq $128,%%rsp\n\t" \ 1379 VALGRIND_CFI_EPILOGUE \ 1380 : /*out*/ "=a" (_res) \ 1381 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1382 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ 1383 ); \ 1384 lval = (__typeof__(lval)) _res; \ 1385 } while (0) 1386 1387 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 1388 do { \ 1389 volatile OrigFn _orig = (orig); \ 1390 volatile unsigned long _argvec[5]; \ 1391 volatile unsigned long _res; \ 1392 _argvec[0] = (unsigned long)_orig.nraddr; \ 1393 _argvec[1] = (unsigned long)(arg1); \ 1394 _argvec[2] = (unsigned long)(arg2); \ 1395 _argvec[3] = (unsigned long)(arg3); \ 1396 _argvec[4] = (unsigned long)(arg4); \ 1397 __asm__ volatile( \ 1398 VALGRIND_CFI_PROLOGUE \ 1399 "subq $128,%%rsp\n\t" \ 1400 "movq 32(%%rax), %%rcx\n\t" \ 1401 "movq 24(%%rax), %%rdx\n\t" \ 1402 "movq 16(%%rax), %%rsi\n\t" \ 1403 "movq 8(%%rax), %%rdi\n\t" \ 1404 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1405 VALGRIND_CALL_NOREDIR_RAX \ 1406 "addq $128,%%rsp\n\t" \ 1407 VALGRIND_CFI_EPILOGUE \ 1408 : /*out*/ "=a" (_res) \ 1409 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1410 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ 1411 ); \ 1412 lval = (__typeof__(lval)) _res; \ 1413 } while (0) 1414 1415 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 1416 do { \ 1417 volatile OrigFn _orig = (orig); \ 1418 volatile unsigned long _argvec[6]; \ 1419 volatile unsigned long _res; \ 1420 _argvec[0] = (unsigned long)_orig.nraddr; \ 1421 _argvec[1] = (unsigned long)(arg1); \ 1422 _argvec[2] = (unsigned long)(arg2); \ 1423 _argvec[3] = (unsigned long)(arg3); \ 1424 _argvec[4] = (unsigned long)(arg4); \ 1425 _argvec[5] = (unsigned long)(arg5); \ 1426 __asm__ volatile( \ 1427 VALGRIND_CFI_PROLOGUE \ 1428 "subq $128,%%rsp\n\t" \ 1429 "movq 40(%%rax), %%r8\n\t" \ 1430 "movq 32(%%rax), %%rcx\n\t" \ 1431 "movq 24(%%rax), %%rdx\n\t" \ 1432 "movq 16(%%rax), %%rsi\n\t" \ 1433 "movq 8(%%rax), %%rdi\n\t" \ 1434 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1435 VALGRIND_CALL_NOREDIR_RAX \ 1436 "addq $128,%%rsp\n\t" \ 1437 VALGRIND_CFI_EPILOGUE \ 1438 : /*out*/ "=a" (_res) \ 1439 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1440 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ 1441 ); \ 1442 lval = (__typeof__(lval)) _res; \ 1443 } while (0) 1444 1445 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 1446 do { \ 1447 volatile OrigFn _orig = (orig); \ 1448 volatile unsigned long _argvec[7]; \ 1449 volatile unsigned long _res; \ 1450 _argvec[0] = (unsigned long)_orig.nraddr; \ 1451 _argvec[1] = (unsigned long)(arg1); \ 1452 _argvec[2] = (unsigned long)(arg2); \ 1453 _argvec[3] = (unsigned long)(arg3); \ 1454 _argvec[4] = (unsigned long)(arg4); \ 1455 _argvec[5] = (unsigned long)(arg5); \ 1456 _argvec[6] = (unsigned long)(arg6); \ 1457 __asm__ volatile( \ 1458 VALGRIND_CFI_PROLOGUE \ 1459 "subq $128,%%rsp\n\t" \ 1460 "movq 48(%%rax), %%r9\n\t" \ 1461 "movq 40(%%rax), %%r8\n\t" \ 1462 "movq 32(%%rax), %%rcx\n\t" \ 1463 "movq 24(%%rax), %%rdx\n\t" \ 1464 "movq 16(%%rax), %%rsi\n\t" \ 1465 "movq 8(%%rax), %%rdi\n\t" \ 1466 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1467 VALGRIND_CALL_NOREDIR_RAX \ 1468 "addq $128,%%rsp\n\t" \ 1469 VALGRIND_CFI_EPILOGUE \ 1470 : /*out*/ "=a" (_res) \ 1471 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1472 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ 1473 ); \ 1474 lval = (__typeof__(lval)) _res; \ 1475 } while (0) 1476 1477 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1478 arg7) \ 1479 do { \ 1480 volatile OrigFn _orig = (orig); \ 1481 volatile unsigned long _argvec[8]; \ 1482 volatile unsigned long _res; \ 1483 _argvec[0] = (unsigned long)_orig.nraddr; \ 1484 _argvec[1] = (unsigned long)(arg1); \ 1485 _argvec[2] = (unsigned long)(arg2); \ 1486 _argvec[3] = (unsigned long)(arg3); \ 1487 _argvec[4] = (unsigned long)(arg4); \ 1488 _argvec[5] = (unsigned long)(arg5); \ 1489 _argvec[6] = (unsigned long)(arg6); \ 1490 _argvec[7] = (unsigned long)(arg7); \ 1491 __asm__ volatile( \ 1492 VALGRIND_CFI_PROLOGUE \ 1493 "subq $136,%%rsp\n\t" \ 1494 "pushq 56(%%rax)\n\t" \ 1495 "movq 48(%%rax), %%r9\n\t" \ 1496 "movq 40(%%rax), %%r8\n\t" \ 1497 "movq 32(%%rax), %%rcx\n\t" \ 1498 "movq 24(%%rax), %%rdx\n\t" \ 1499 "movq 16(%%rax), %%rsi\n\t" \ 1500 "movq 8(%%rax), %%rdi\n\t" \ 1501 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1502 VALGRIND_CALL_NOREDIR_RAX \ 1503 "addq $8, %%rsp\n" \ 1504 "addq $136,%%rsp\n\t" \ 1505 VALGRIND_CFI_EPILOGUE \ 1506 : /*out*/ "=a" (_res) \ 1507 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1508 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ 1509 ); \ 1510 lval = (__typeof__(lval)) _res; \ 1511 } while (0) 1512 1513 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1514 arg7,arg8) \ 1515 do { \ 1516 volatile OrigFn _orig = (orig); \ 1517 volatile unsigned long _argvec[9]; \ 1518 volatile unsigned long _res; \ 1519 _argvec[0] = (unsigned long)_orig.nraddr; \ 1520 _argvec[1] = (unsigned long)(arg1); \ 1521 _argvec[2] = (unsigned long)(arg2); \ 1522 _argvec[3] = (unsigned long)(arg3); \ 1523 _argvec[4] = (unsigned long)(arg4); \ 1524 _argvec[5] = (unsigned long)(arg5); \ 1525 _argvec[6] = (unsigned long)(arg6); \ 1526 _argvec[7] = (unsigned long)(arg7); \ 1527 _argvec[8] = (unsigned long)(arg8); \ 1528 __asm__ volatile( \ 1529 VALGRIND_CFI_PROLOGUE \ 1530 "subq $128,%%rsp\n\t" \ 1531 "pushq 64(%%rax)\n\t" \ 1532 "pushq 56(%%rax)\n\t" \ 1533 "movq 48(%%rax), %%r9\n\t" \ 1534 "movq 40(%%rax), %%r8\n\t" \ 1535 "movq 32(%%rax), %%rcx\n\t" \ 1536 "movq 24(%%rax), %%rdx\n\t" \ 1537 "movq 16(%%rax), %%rsi\n\t" \ 1538 "movq 8(%%rax), %%rdi\n\t" \ 1539 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1540 VALGRIND_CALL_NOREDIR_RAX \ 1541 "addq $16, %%rsp\n" \ 1542 "addq $128,%%rsp\n\t" \ 1543 VALGRIND_CFI_EPILOGUE \ 1544 : /*out*/ "=a" (_res) \ 1545 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1546 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ 1547 ); \ 1548 lval = (__typeof__(lval)) _res; \ 1549 } while (0) 1550 1551 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1552 arg7,arg8,arg9) \ 1553 do { \ 1554 volatile OrigFn _orig = (orig); \ 1555 volatile unsigned long _argvec[10]; \ 1556 volatile unsigned long _res; \ 1557 _argvec[0] = (unsigned long)_orig.nraddr; \ 1558 _argvec[1] = (unsigned long)(arg1); \ 1559 _argvec[2] = (unsigned long)(arg2); \ 1560 _argvec[3] = (unsigned long)(arg3); \ 1561 _argvec[4] = (unsigned long)(arg4); \ 1562 _argvec[5] = (unsigned long)(arg5); \ 1563 _argvec[6] = (unsigned long)(arg6); \ 1564 _argvec[7] = (unsigned long)(arg7); \ 1565 _argvec[8] = (unsigned long)(arg8); \ 1566 _argvec[9] = (unsigned long)(arg9); \ 1567 __asm__ volatile( \ 1568 VALGRIND_CFI_PROLOGUE \ 1569 "subq $136,%%rsp\n\t" \ 1570 "pushq 72(%%rax)\n\t" \ 1571 "pushq 64(%%rax)\n\t" \ 1572 "pushq 56(%%rax)\n\t" \ 1573 "movq 48(%%rax), %%r9\n\t" \ 1574 "movq 40(%%rax), %%r8\n\t" \ 1575 "movq 32(%%rax), %%rcx\n\t" \ 1576 "movq 24(%%rax), %%rdx\n\t" \ 1577 "movq 16(%%rax), %%rsi\n\t" \ 1578 "movq 8(%%rax), %%rdi\n\t" \ 1579 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1580 VALGRIND_CALL_NOREDIR_RAX \ 1581 "addq $24, %%rsp\n" \ 1582 "addq $136,%%rsp\n\t" \ 1583 VALGRIND_CFI_EPILOGUE \ 1584 : /*out*/ "=a" (_res) \ 1585 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1586 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ 1587 ); \ 1588 lval = (__typeof__(lval)) _res; \ 1589 } while (0) 1590 1591 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1592 arg7,arg8,arg9,arg10) \ 1593 do { \ 1594 volatile OrigFn _orig = (orig); \ 1595 volatile unsigned long _argvec[11]; \ 1596 volatile unsigned long _res; \ 1597 _argvec[0] = (unsigned long)_orig.nraddr; \ 1598 _argvec[1] = (unsigned long)(arg1); \ 1599 _argvec[2] = (unsigned long)(arg2); \ 1600 _argvec[3] = (unsigned long)(arg3); \ 1601 _argvec[4] = (unsigned long)(arg4); \ 1602 _argvec[5] = (unsigned long)(arg5); \ 1603 _argvec[6] = (unsigned long)(arg6); \ 1604 _argvec[7] = (unsigned long)(arg7); \ 1605 _argvec[8] = (unsigned long)(arg8); \ 1606 _argvec[9] = (unsigned long)(arg9); \ 1607 _argvec[10] = (unsigned long)(arg10); \ 1608 __asm__ volatile( \ 1609 VALGRIND_CFI_PROLOGUE \ 1610 "subq $128,%%rsp\n\t" \ 1611 "pushq 80(%%rax)\n\t" \ 1612 "pushq 72(%%rax)\n\t" \ 1613 "pushq 64(%%rax)\n\t" \ 1614 "pushq 56(%%rax)\n\t" \ 1615 "movq 48(%%rax), %%r9\n\t" \ 1616 "movq 40(%%rax), %%r8\n\t" \ 1617 "movq 32(%%rax), %%rcx\n\t" \ 1618 "movq 24(%%rax), %%rdx\n\t" \ 1619 "movq 16(%%rax), %%rsi\n\t" \ 1620 "movq 8(%%rax), %%rdi\n\t" \ 1621 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1622 VALGRIND_CALL_NOREDIR_RAX \ 1623 "addq $32, %%rsp\n" \ 1624 "addq $128,%%rsp\n\t" \ 1625 VALGRIND_CFI_EPILOGUE \ 1626 : /*out*/ "=a" (_res) \ 1627 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1628 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ 1629 ); \ 1630 lval = (__typeof__(lval)) _res; \ 1631 } while (0) 1632 1633 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1634 arg7,arg8,arg9,arg10,arg11) \ 1635 do { \ 1636 volatile OrigFn _orig = (orig); \ 1637 volatile unsigned long _argvec[12]; \ 1638 volatile unsigned long _res; \ 1639 _argvec[0] = (unsigned long)_orig.nraddr; \ 1640 _argvec[1] = (unsigned long)(arg1); \ 1641 _argvec[2] = (unsigned long)(arg2); \ 1642 _argvec[3] = (unsigned long)(arg3); \ 1643 _argvec[4] = (unsigned long)(arg4); \ 1644 _argvec[5] = (unsigned long)(arg5); \ 1645 _argvec[6] = (unsigned long)(arg6); \ 1646 _argvec[7] = (unsigned long)(arg7); \ 1647 _argvec[8] = (unsigned long)(arg8); \ 1648 _argvec[9] = (unsigned long)(arg9); \ 1649 _argvec[10] = (unsigned long)(arg10); \ 1650 _argvec[11] = (unsigned long)(arg11); \ 1651 __asm__ volatile( \ 1652 VALGRIND_CFI_PROLOGUE \ 1653 "subq $136,%%rsp\n\t" \ 1654 "pushq 88(%%rax)\n\t" \ 1655 "pushq 80(%%rax)\n\t" \ 1656 "pushq 72(%%rax)\n\t" \ 1657 "pushq 64(%%rax)\n\t" \ 1658 "pushq 56(%%rax)\n\t" \ 1659 "movq 48(%%rax), %%r9\n\t" \ 1660 "movq 40(%%rax), %%r8\n\t" \ 1661 "movq 32(%%rax), %%rcx\n\t" \ 1662 "movq 24(%%rax), %%rdx\n\t" \ 1663 "movq 16(%%rax), %%rsi\n\t" \ 1664 "movq 8(%%rax), %%rdi\n\t" \ 1665 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1666 VALGRIND_CALL_NOREDIR_RAX \ 1667 "addq $40, %%rsp\n" \ 1668 "addq $136,%%rsp\n\t" \ 1669 VALGRIND_CFI_EPILOGUE \ 1670 : /*out*/ "=a" (_res) \ 1671 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1672 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ 1673 ); \ 1674 lval = (__typeof__(lval)) _res; \ 1675 } while (0) 1676 1677 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1678 arg7,arg8,arg9,arg10,arg11,arg12) \ 1679 do { \ 1680 volatile OrigFn _orig = (orig); \ 1681 volatile unsigned long _argvec[13]; \ 1682 volatile unsigned long _res; \ 1683 _argvec[0] = (unsigned long)_orig.nraddr; \ 1684 _argvec[1] = (unsigned long)(arg1); \ 1685 _argvec[2] = (unsigned long)(arg2); \ 1686 _argvec[3] = (unsigned long)(arg3); \ 1687 _argvec[4] = (unsigned long)(arg4); \ 1688 _argvec[5] = (unsigned long)(arg5); \ 1689 _argvec[6] = (unsigned long)(arg6); \ 1690 _argvec[7] = (unsigned long)(arg7); \ 1691 _argvec[8] = (unsigned long)(arg8); \ 1692 _argvec[9] = (unsigned long)(arg9); \ 1693 _argvec[10] = (unsigned long)(arg10); \ 1694 _argvec[11] = (unsigned long)(arg11); \ 1695 _argvec[12] = (unsigned long)(arg12); \ 1696 __asm__ volatile( \ 1697 VALGRIND_CFI_PROLOGUE \ 1698 "subq $128,%%rsp\n\t" \ 1699 "pushq 96(%%rax)\n\t" \ 1700 "pushq 88(%%rax)\n\t" \ 1701 "pushq 80(%%rax)\n\t" \ 1702 "pushq 72(%%rax)\n\t" \ 1703 "pushq 64(%%rax)\n\t" \ 1704 "pushq 56(%%rax)\n\t" \ 1705 "movq 48(%%rax), %%r9\n\t" \ 1706 "movq 40(%%rax), %%r8\n\t" \ 1707 "movq 32(%%rax), %%rcx\n\t" \ 1708 "movq 24(%%rax), %%rdx\n\t" \ 1709 "movq 16(%%rax), %%rsi\n\t" \ 1710 "movq 8(%%rax), %%rdi\n\t" \ 1711 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1712 VALGRIND_CALL_NOREDIR_RAX \ 1713 "addq $48, %%rsp\n" \ 1714 "addq $128,%%rsp\n\t" \ 1715 VALGRIND_CFI_EPILOGUE \ 1716 : /*out*/ "=a" (_res) \ 1717 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1718 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ 1719 ); \ 1720 lval = (__typeof__(lval)) _res; \ 1721 } while (0) 1722 1723 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin */ 1724 1725 /* ------------------------ ppc32-linux ------------------------ */ 1726 1727 #if defined(PLAT_ppc32_linux) 1728 1729 /* This is useful for finding out about the on-stack stuff: 1730 1731 extern int f9 ( int,int,int,int,int,int,int,int,int ); 1732 extern int f10 ( int,int,int,int,int,int,int,int,int,int ); 1733 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int ); 1734 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int ); 1735 1736 int g9 ( void ) { 1737 return f9(11,22,33,44,55,66,77,88,99); 1738 } 1739 int g10 ( void ) { 1740 return f10(11,22,33,44,55,66,77,88,99,110); 1741 } 1742 int g11 ( void ) { 1743 return f11(11,22,33,44,55,66,77,88,99,110,121); 1744 } 1745 int g12 ( void ) { 1746 return f12(11,22,33,44,55,66,77,88,99,110,121,132); 1747 } 1748 */ 1749 1750 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ 1751 1752 /* These regs are trashed by the hidden call. */ 1753 #define __CALLER_SAVED_REGS \ 1754 "lr", "ctr", "xer", \ 1755 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ 1756 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ 1757 "r11", "r12", "r13" 1758 1759 /* These CALL_FN_ macros assume that on ppc32-linux, 1760 sizeof(unsigned long) == 4. */ 1761 1762 #define CALL_FN_W_v(lval, orig) \ 1763 do { \ 1764 volatile OrigFn _orig = (orig); \ 1765 volatile unsigned long _argvec[1]; \ 1766 volatile unsigned long _res; \ 1767 _argvec[0] = (unsigned long)_orig.nraddr; \ 1768 __asm__ volatile( \ 1769 "mr 11,%1\n\t" \ 1770 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1771 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1772 "mr %0,3" \ 1773 : /*out*/ "=r" (_res) \ 1774 : /*in*/ "r" (&_argvec[0]) \ 1775 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1776 ); \ 1777 lval = (__typeof__(lval)) _res; \ 1778 } while (0) 1779 1780 #define CALL_FN_W_W(lval, orig, arg1) \ 1781 do { \ 1782 volatile OrigFn _orig = (orig); \ 1783 volatile unsigned long _argvec[2]; \ 1784 volatile unsigned long _res; \ 1785 _argvec[0] = (unsigned long)_orig.nraddr; \ 1786 _argvec[1] = (unsigned long)arg1; \ 1787 __asm__ volatile( \ 1788 "mr 11,%1\n\t" \ 1789 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1790 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1791 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1792 "mr %0,3" \ 1793 : /*out*/ "=r" (_res) \ 1794 : /*in*/ "r" (&_argvec[0]) \ 1795 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1796 ); \ 1797 lval = (__typeof__(lval)) _res; \ 1798 } while (0) 1799 1800 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 1801 do { \ 1802 volatile OrigFn _orig = (orig); \ 1803 volatile unsigned long _argvec[3]; \ 1804 volatile unsigned long _res; \ 1805 _argvec[0] = (unsigned long)_orig.nraddr; \ 1806 _argvec[1] = (unsigned long)arg1; \ 1807 _argvec[2] = (unsigned long)arg2; \ 1808 __asm__ volatile( \ 1809 "mr 11,%1\n\t" \ 1810 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1811 "lwz 4,8(11)\n\t" \ 1812 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1813 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1814 "mr %0,3" \ 1815 : /*out*/ "=r" (_res) \ 1816 : /*in*/ "r" (&_argvec[0]) \ 1817 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1818 ); \ 1819 lval = (__typeof__(lval)) _res; \ 1820 } while (0) 1821 1822 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 1823 do { \ 1824 volatile OrigFn _orig = (orig); \ 1825 volatile unsigned long _argvec[4]; \ 1826 volatile unsigned long _res; \ 1827 _argvec[0] = (unsigned long)_orig.nraddr; \ 1828 _argvec[1] = (unsigned long)arg1; \ 1829 _argvec[2] = (unsigned long)arg2; \ 1830 _argvec[3] = (unsigned long)arg3; \ 1831 __asm__ volatile( \ 1832 "mr 11,%1\n\t" \ 1833 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1834 "lwz 4,8(11)\n\t" \ 1835 "lwz 5,12(11)\n\t" \ 1836 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1837 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1838 "mr %0,3" \ 1839 : /*out*/ "=r" (_res) \ 1840 : /*in*/ "r" (&_argvec[0]) \ 1841 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1842 ); \ 1843 lval = (__typeof__(lval)) _res; \ 1844 } while (0) 1845 1846 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 1847 do { \ 1848 volatile OrigFn _orig = (orig); \ 1849 volatile unsigned long _argvec[5]; \ 1850 volatile unsigned long _res; \ 1851 _argvec[0] = (unsigned long)_orig.nraddr; \ 1852 _argvec[1] = (unsigned long)arg1; \ 1853 _argvec[2] = (unsigned long)arg2; \ 1854 _argvec[3] = (unsigned long)arg3; \ 1855 _argvec[4] = (unsigned long)arg4; \ 1856 __asm__ volatile( \ 1857 "mr 11,%1\n\t" \ 1858 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1859 "lwz 4,8(11)\n\t" \ 1860 "lwz 5,12(11)\n\t" \ 1861 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 1862 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1863 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1864 "mr %0,3" \ 1865 : /*out*/ "=r" (_res) \ 1866 : /*in*/ "r" (&_argvec[0]) \ 1867 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1868 ); \ 1869 lval = (__typeof__(lval)) _res; \ 1870 } while (0) 1871 1872 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 1873 do { \ 1874 volatile OrigFn _orig = (orig); \ 1875 volatile unsigned long _argvec[6]; \ 1876 volatile unsigned long _res; \ 1877 _argvec[0] = (unsigned long)_orig.nraddr; \ 1878 _argvec[1] = (unsigned long)arg1; \ 1879 _argvec[2] = (unsigned long)arg2; \ 1880 _argvec[3] = (unsigned long)arg3; \ 1881 _argvec[4] = (unsigned long)arg4; \ 1882 _argvec[5] = (unsigned long)arg5; \ 1883 __asm__ volatile( \ 1884 "mr 11,%1\n\t" \ 1885 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1886 "lwz 4,8(11)\n\t" \ 1887 "lwz 5,12(11)\n\t" \ 1888 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 1889 "lwz 7,20(11)\n\t" \ 1890 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1891 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1892 "mr %0,3" \ 1893 : /*out*/ "=r" (_res) \ 1894 : /*in*/ "r" (&_argvec[0]) \ 1895 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1896 ); \ 1897 lval = (__typeof__(lval)) _res; \ 1898 } while (0) 1899 1900 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 1901 do { \ 1902 volatile OrigFn _orig = (orig); \ 1903 volatile unsigned long _argvec[7]; \ 1904 volatile unsigned long _res; \ 1905 _argvec[0] = (unsigned long)_orig.nraddr; \ 1906 _argvec[1] = (unsigned long)arg1; \ 1907 _argvec[2] = (unsigned long)arg2; \ 1908 _argvec[3] = (unsigned long)arg3; \ 1909 _argvec[4] = (unsigned long)arg4; \ 1910 _argvec[5] = (unsigned long)arg5; \ 1911 _argvec[6] = (unsigned long)arg6; \ 1912 __asm__ volatile( \ 1913 "mr 11,%1\n\t" \ 1914 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1915 "lwz 4,8(11)\n\t" \ 1916 "lwz 5,12(11)\n\t" \ 1917 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 1918 "lwz 7,20(11)\n\t" \ 1919 "lwz 8,24(11)\n\t" \ 1920 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1921 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1922 "mr %0,3" \ 1923 : /*out*/ "=r" (_res) \ 1924 : /*in*/ "r" (&_argvec[0]) \ 1925 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1926 ); \ 1927 lval = (__typeof__(lval)) _res; \ 1928 } while (0) 1929 1930 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1931 arg7) \ 1932 do { \ 1933 volatile OrigFn _orig = (orig); \ 1934 volatile unsigned long _argvec[8]; \ 1935 volatile unsigned long _res; \ 1936 _argvec[0] = (unsigned long)_orig.nraddr; \ 1937 _argvec[1] = (unsigned long)arg1; \ 1938 _argvec[2] = (unsigned long)arg2; \ 1939 _argvec[3] = (unsigned long)arg3; \ 1940 _argvec[4] = (unsigned long)arg4; \ 1941 _argvec[5] = (unsigned long)arg5; \ 1942 _argvec[6] = (unsigned long)arg6; \ 1943 _argvec[7] = (unsigned long)arg7; \ 1944 __asm__ volatile( \ 1945 "mr 11,%1\n\t" \ 1946 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1947 "lwz 4,8(11)\n\t" \ 1948 "lwz 5,12(11)\n\t" \ 1949 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 1950 "lwz 7,20(11)\n\t" \ 1951 "lwz 8,24(11)\n\t" \ 1952 "lwz 9,28(11)\n\t" \ 1953 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1954 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1955 "mr %0,3" \ 1956 : /*out*/ "=r" (_res) \ 1957 : /*in*/ "r" (&_argvec[0]) \ 1958 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1959 ); \ 1960 lval = (__typeof__(lval)) _res; \ 1961 } while (0) 1962 1963 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1964 arg7,arg8) \ 1965 do { \ 1966 volatile OrigFn _orig = (orig); \ 1967 volatile unsigned long _argvec[9]; \ 1968 volatile unsigned long _res; \ 1969 _argvec[0] = (unsigned long)_orig.nraddr; \ 1970 _argvec[1] = (unsigned long)arg1; \ 1971 _argvec[2] = (unsigned long)arg2; \ 1972 _argvec[3] = (unsigned long)arg3; \ 1973 _argvec[4] = (unsigned long)arg4; \ 1974 _argvec[5] = (unsigned long)arg5; \ 1975 _argvec[6] = (unsigned long)arg6; \ 1976 _argvec[7] = (unsigned long)arg7; \ 1977 _argvec[8] = (unsigned long)arg8; \ 1978 __asm__ volatile( \ 1979 "mr 11,%1\n\t" \ 1980 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 1981 "lwz 4,8(11)\n\t" \ 1982 "lwz 5,12(11)\n\t" \ 1983 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 1984 "lwz 7,20(11)\n\t" \ 1985 "lwz 8,24(11)\n\t" \ 1986 "lwz 9,28(11)\n\t" \ 1987 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 1988 "lwz 11,0(11)\n\t" /* target->r11 */ \ 1989 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 1990 "mr %0,3" \ 1991 : /*out*/ "=r" (_res) \ 1992 : /*in*/ "r" (&_argvec[0]) \ 1993 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 1994 ); \ 1995 lval = (__typeof__(lval)) _res; \ 1996 } while (0) 1997 1998 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1999 arg7,arg8,arg9) \ 2000 do { \ 2001 volatile OrigFn _orig = (orig); \ 2002 volatile unsigned long _argvec[10]; \ 2003 volatile unsigned long _res; \ 2004 _argvec[0] = (unsigned long)_orig.nraddr; \ 2005 _argvec[1] = (unsigned long)arg1; \ 2006 _argvec[2] = (unsigned long)arg2; \ 2007 _argvec[3] = (unsigned long)arg3; \ 2008 _argvec[4] = (unsigned long)arg4; \ 2009 _argvec[5] = (unsigned long)arg5; \ 2010 _argvec[6] = (unsigned long)arg6; \ 2011 _argvec[7] = (unsigned long)arg7; \ 2012 _argvec[8] = (unsigned long)arg8; \ 2013 _argvec[9] = (unsigned long)arg9; \ 2014 __asm__ volatile( \ 2015 "mr 11,%1\n\t" \ 2016 "addi 1,1,-16\n\t" \ 2017 /* arg9 */ \ 2018 "lwz 3,36(11)\n\t" \ 2019 "stw 3,8(1)\n\t" \ 2020 /* args1-8 */ \ 2021 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 2022 "lwz 4,8(11)\n\t" \ 2023 "lwz 5,12(11)\n\t" \ 2024 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 2025 "lwz 7,20(11)\n\t" \ 2026 "lwz 8,24(11)\n\t" \ 2027 "lwz 9,28(11)\n\t" \ 2028 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 2029 "lwz 11,0(11)\n\t" /* target->r11 */ \ 2030 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2031 "addi 1,1,16\n\t" \ 2032 "mr %0,3" \ 2033 : /*out*/ "=r" (_res) \ 2034 : /*in*/ "r" (&_argvec[0]) \ 2035 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2036 ); \ 2037 lval = (__typeof__(lval)) _res; \ 2038 } while (0) 2039 2040 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2041 arg7,arg8,arg9,arg10) \ 2042 do { \ 2043 volatile OrigFn _orig = (orig); \ 2044 volatile unsigned long _argvec[11]; \ 2045 volatile unsigned long _res; \ 2046 _argvec[0] = (unsigned long)_orig.nraddr; \ 2047 _argvec[1] = (unsigned long)arg1; \ 2048 _argvec[2] = (unsigned long)arg2; \ 2049 _argvec[3] = (unsigned long)arg3; \ 2050 _argvec[4] = (unsigned long)arg4; \ 2051 _argvec[5] = (unsigned long)arg5; \ 2052 _argvec[6] = (unsigned long)arg6; \ 2053 _argvec[7] = (unsigned long)arg7; \ 2054 _argvec[8] = (unsigned long)arg8; \ 2055 _argvec[9] = (unsigned long)arg9; \ 2056 _argvec[10] = (unsigned long)arg10; \ 2057 __asm__ volatile( \ 2058 "mr 11,%1\n\t" \ 2059 "addi 1,1,-16\n\t" \ 2060 /* arg10 */ \ 2061 "lwz 3,40(11)\n\t" \ 2062 "stw 3,12(1)\n\t" \ 2063 /* arg9 */ \ 2064 "lwz 3,36(11)\n\t" \ 2065 "stw 3,8(1)\n\t" \ 2066 /* args1-8 */ \ 2067 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 2068 "lwz 4,8(11)\n\t" \ 2069 "lwz 5,12(11)\n\t" \ 2070 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 2071 "lwz 7,20(11)\n\t" \ 2072 "lwz 8,24(11)\n\t" \ 2073 "lwz 9,28(11)\n\t" \ 2074 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 2075 "lwz 11,0(11)\n\t" /* target->r11 */ \ 2076 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2077 "addi 1,1,16\n\t" \ 2078 "mr %0,3" \ 2079 : /*out*/ "=r" (_res) \ 2080 : /*in*/ "r" (&_argvec[0]) \ 2081 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2082 ); \ 2083 lval = (__typeof__(lval)) _res; \ 2084 } while (0) 2085 2086 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2087 arg7,arg8,arg9,arg10,arg11) \ 2088 do { \ 2089 volatile OrigFn _orig = (orig); \ 2090 volatile unsigned long _argvec[12]; \ 2091 volatile unsigned long _res; \ 2092 _argvec[0] = (unsigned long)_orig.nraddr; \ 2093 _argvec[1] = (unsigned long)arg1; \ 2094 _argvec[2] = (unsigned long)arg2; \ 2095 _argvec[3] = (unsigned long)arg3; \ 2096 _argvec[4] = (unsigned long)arg4; \ 2097 _argvec[5] = (unsigned long)arg5; \ 2098 _argvec[6] = (unsigned long)arg6; \ 2099 _argvec[7] = (unsigned long)arg7; \ 2100 _argvec[8] = (unsigned long)arg8; \ 2101 _argvec[9] = (unsigned long)arg9; \ 2102 _argvec[10] = (unsigned long)arg10; \ 2103 _argvec[11] = (unsigned long)arg11; \ 2104 __asm__ volatile( \ 2105 "mr 11,%1\n\t" \ 2106 "addi 1,1,-32\n\t" \ 2107 /* arg11 */ \ 2108 "lwz 3,44(11)\n\t" \ 2109 "stw 3,16(1)\n\t" \ 2110 /* arg10 */ \ 2111 "lwz 3,40(11)\n\t" \ 2112 "stw 3,12(1)\n\t" \ 2113 /* arg9 */ \ 2114 "lwz 3,36(11)\n\t" \ 2115 "stw 3,8(1)\n\t" \ 2116 /* args1-8 */ \ 2117 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 2118 "lwz 4,8(11)\n\t" \ 2119 "lwz 5,12(11)\n\t" \ 2120 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 2121 "lwz 7,20(11)\n\t" \ 2122 "lwz 8,24(11)\n\t" \ 2123 "lwz 9,28(11)\n\t" \ 2124 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 2125 "lwz 11,0(11)\n\t" /* target->r11 */ \ 2126 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2127 "addi 1,1,32\n\t" \ 2128 "mr %0,3" \ 2129 : /*out*/ "=r" (_res) \ 2130 : /*in*/ "r" (&_argvec[0]) \ 2131 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2132 ); \ 2133 lval = (__typeof__(lval)) _res; \ 2134 } while (0) 2135 2136 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2137 arg7,arg8,arg9,arg10,arg11,arg12) \ 2138 do { \ 2139 volatile OrigFn _orig = (orig); \ 2140 volatile unsigned long _argvec[13]; \ 2141 volatile unsigned long _res; \ 2142 _argvec[0] = (unsigned long)_orig.nraddr; \ 2143 _argvec[1] = (unsigned long)arg1; \ 2144 _argvec[2] = (unsigned long)arg2; \ 2145 _argvec[3] = (unsigned long)arg3; \ 2146 _argvec[4] = (unsigned long)arg4; \ 2147 _argvec[5] = (unsigned long)arg5; \ 2148 _argvec[6] = (unsigned long)arg6; \ 2149 _argvec[7] = (unsigned long)arg7; \ 2150 _argvec[8] = (unsigned long)arg8; \ 2151 _argvec[9] = (unsigned long)arg9; \ 2152 _argvec[10] = (unsigned long)arg10; \ 2153 _argvec[11] = (unsigned long)arg11; \ 2154 _argvec[12] = (unsigned long)arg12; \ 2155 __asm__ volatile( \ 2156 "mr 11,%1\n\t" \ 2157 "addi 1,1,-32\n\t" \ 2158 /* arg12 */ \ 2159 "lwz 3,48(11)\n\t" \ 2160 "stw 3,20(1)\n\t" \ 2161 /* arg11 */ \ 2162 "lwz 3,44(11)\n\t" \ 2163 "stw 3,16(1)\n\t" \ 2164 /* arg10 */ \ 2165 "lwz 3,40(11)\n\t" \ 2166 "stw 3,12(1)\n\t" \ 2167 /* arg9 */ \ 2168 "lwz 3,36(11)\n\t" \ 2169 "stw 3,8(1)\n\t" \ 2170 /* args1-8 */ \ 2171 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 2172 "lwz 4,8(11)\n\t" \ 2173 "lwz 5,12(11)\n\t" \ 2174 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 2175 "lwz 7,20(11)\n\t" \ 2176 "lwz 8,24(11)\n\t" \ 2177 "lwz 9,28(11)\n\t" \ 2178 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 2179 "lwz 11,0(11)\n\t" /* target->r11 */ \ 2180 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2181 "addi 1,1,32\n\t" \ 2182 "mr %0,3" \ 2183 : /*out*/ "=r" (_res) \ 2184 : /*in*/ "r" (&_argvec[0]) \ 2185 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2186 ); \ 2187 lval = (__typeof__(lval)) _res; \ 2188 } while (0) 2189 2190 #endif /* PLAT_ppc32_linux */ 2191 2192 /* ------------------------ ppc64-linux ------------------------ */ 2193 2194 #if defined(PLAT_ppc64_linux) 2195 2196 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ 2197 2198 /* These regs are trashed by the hidden call. */ 2199 #define __CALLER_SAVED_REGS \ 2200 "lr", "ctr", "xer", \ 2201 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ 2202 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ 2203 "r11", "r12", "r13" 2204 2205 /* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned 2206 long) == 8. */ 2207 2208 #define CALL_FN_W_v(lval, orig) \ 2209 do { \ 2210 volatile OrigFn _orig = (orig); \ 2211 volatile unsigned long _argvec[3+0]; \ 2212 volatile unsigned long _res; \ 2213 /* _argvec[0] holds current r2 across the call */ \ 2214 _argvec[1] = (unsigned long)_orig.r2; \ 2215 _argvec[2] = (unsigned long)_orig.nraddr; \ 2216 __asm__ volatile( \ 2217 "mr 11,%1\n\t" \ 2218 "std 2,-16(11)\n\t" /* save tocptr */ \ 2219 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2220 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2221 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2222 "mr 11,%1\n\t" \ 2223 "mr %0,3\n\t" \ 2224 "ld 2,-16(11)" /* restore tocptr */ \ 2225 : /*out*/ "=r" (_res) \ 2226 : /*in*/ "r" (&_argvec[2]) \ 2227 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2228 ); \ 2229 lval = (__typeof__(lval)) _res; \ 2230 } while (0) 2231 2232 #define CALL_FN_W_W(lval, orig, arg1) \ 2233 do { \ 2234 volatile OrigFn _orig = (orig); \ 2235 volatile unsigned long _argvec[3+1]; \ 2236 volatile unsigned long _res; \ 2237 /* _argvec[0] holds current r2 across the call */ \ 2238 _argvec[1] = (unsigned long)_orig.r2; \ 2239 _argvec[2] = (unsigned long)_orig.nraddr; \ 2240 _argvec[2+1] = (unsigned long)arg1; \ 2241 __asm__ volatile( \ 2242 "mr 11,%1\n\t" \ 2243 "std 2,-16(11)\n\t" /* save tocptr */ \ 2244 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2245 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2246 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2247 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2248 "mr 11,%1\n\t" \ 2249 "mr %0,3\n\t" \ 2250 "ld 2,-16(11)" /* restore tocptr */ \ 2251 : /*out*/ "=r" (_res) \ 2252 : /*in*/ "r" (&_argvec[2]) \ 2253 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2254 ); \ 2255 lval = (__typeof__(lval)) _res; \ 2256 } while (0) 2257 2258 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 2259 do { \ 2260 volatile OrigFn _orig = (orig); \ 2261 volatile unsigned long _argvec[3+2]; \ 2262 volatile unsigned long _res; \ 2263 /* _argvec[0] holds current r2 across the call */ \ 2264 _argvec[1] = (unsigned long)_orig.r2; \ 2265 _argvec[2] = (unsigned long)_orig.nraddr; \ 2266 _argvec[2+1] = (unsigned long)arg1; \ 2267 _argvec[2+2] = (unsigned long)arg2; \ 2268 __asm__ volatile( \ 2269 "mr 11,%1\n\t" \ 2270 "std 2,-16(11)\n\t" /* save tocptr */ \ 2271 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2272 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2273 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2274 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2275 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2276 "mr 11,%1\n\t" \ 2277 "mr %0,3\n\t" \ 2278 "ld 2,-16(11)" /* restore tocptr */ \ 2279 : /*out*/ "=r" (_res) \ 2280 : /*in*/ "r" (&_argvec[2]) \ 2281 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2282 ); \ 2283 lval = (__typeof__(lval)) _res; \ 2284 } while (0) 2285 2286 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 2287 do { \ 2288 volatile OrigFn _orig = (orig); \ 2289 volatile unsigned long _argvec[3+3]; \ 2290 volatile unsigned long _res; \ 2291 /* _argvec[0] holds current r2 across the call */ \ 2292 _argvec[1] = (unsigned long)_orig.r2; \ 2293 _argvec[2] = (unsigned long)_orig.nraddr; \ 2294 _argvec[2+1] = (unsigned long)arg1; \ 2295 _argvec[2+2] = (unsigned long)arg2; \ 2296 _argvec[2+3] = (unsigned long)arg3; \ 2297 __asm__ volatile( \ 2298 "mr 11,%1\n\t" \ 2299 "std 2,-16(11)\n\t" /* save tocptr */ \ 2300 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2301 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2302 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2303 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2304 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2305 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2306 "mr 11,%1\n\t" \ 2307 "mr %0,3\n\t" \ 2308 "ld 2,-16(11)" /* restore tocptr */ \ 2309 : /*out*/ "=r" (_res) \ 2310 : /*in*/ "r" (&_argvec[2]) \ 2311 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2312 ); \ 2313 lval = (__typeof__(lval)) _res; \ 2314 } while (0) 2315 2316 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 2317 do { \ 2318 volatile OrigFn _orig = (orig); \ 2319 volatile unsigned long _argvec[3+4]; \ 2320 volatile unsigned long _res; \ 2321 /* _argvec[0] holds current r2 across the call */ \ 2322 _argvec[1] = (unsigned long)_orig.r2; \ 2323 _argvec[2] = (unsigned long)_orig.nraddr; \ 2324 _argvec[2+1] = (unsigned long)arg1; \ 2325 _argvec[2+2] = (unsigned long)arg2; \ 2326 _argvec[2+3] = (unsigned long)arg3; \ 2327 _argvec[2+4] = (unsigned long)arg4; \ 2328 __asm__ volatile( \ 2329 "mr 11,%1\n\t" \ 2330 "std 2,-16(11)\n\t" /* save tocptr */ \ 2331 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2332 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2333 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2334 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2335 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2336 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2337 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2338 "mr 11,%1\n\t" \ 2339 "mr %0,3\n\t" \ 2340 "ld 2,-16(11)" /* restore tocptr */ \ 2341 : /*out*/ "=r" (_res) \ 2342 : /*in*/ "r" (&_argvec[2]) \ 2343 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2344 ); \ 2345 lval = (__typeof__(lval)) _res; \ 2346 } while (0) 2347 2348 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 2349 do { \ 2350 volatile OrigFn _orig = (orig); \ 2351 volatile unsigned long _argvec[3+5]; \ 2352 volatile unsigned long _res; \ 2353 /* _argvec[0] holds current r2 across the call */ \ 2354 _argvec[1] = (unsigned long)_orig.r2; \ 2355 _argvec[2] = (unsigned long)_orig.nraddr; \ 2356 _argvec[2+1] = (unsigned long)arg1; \ 2357 _argvec[2+2] = (unsigned long)arg2; \ 2358 _argvec[2+3] = (unsigned long)arg3; \ 2359 _argvec[2+4] = (unsigned long)arg4; \ 2360 _argvec[2+5] = (unsigned long)arg5; \ 2361 __asm__ volatile( \ 2362 "mr 11,%1\n\t" \ 2363 "std 2,-16(11)\n\t" /* save tocptr */ \ 2364 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2365 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2366 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2367 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2368 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2369 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2370 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2371 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2372 "mr 11,%1\n\t" \ 2373 "mr %0,3\n\t" \ 2374 "ld 2,-16(11)" /* restore tocptr */ \ 2375 : /*out*/ "=r" (_res) \ 2376 : /*in*/ "r" (&_argvec[2]) \ 2377 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2378 ); \ 2379 lval = (__typeof__(lval)) _res; \ 2380 } while (0) 2381 2382 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 2383 do { \ 2384 volatile OrigFn _orig = (orig); \ 2385 volatile unsigned long _argvec[3+6]; \ 2386 volatile unsigned long _res; \ 2387 /* _argvec[0] holds current r2 across the call */ \ 2388 _argvec[1] = (unsigned long)_orig.r2; \ 2389 _argvec[2] = (unsigned long)_orig.nraddr; \ 2390 _argvec[2+1] = (unsigned long)arg1; \ 2391 _argvec[2+2] = (unsigned long)arg2; \ 2392 _argvec[2+3] = (unsigned long)arg3; \ 2393 _argvec[2+4] = (unsigned long)arg4; \ 2394 _argvec[2+5] = (unsigned long)arg5; \ 2395 _argvec[2+6] = (unsigned long)arg6; \ 2396 __asm__ volatile( \ 2397 "mr 11,%1\n\t" \ 2398 "std 2,-16(11)\n\t" /* save tocptr */ \ 2399 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2400 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2401 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2402 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2403 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2404 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2405 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2406 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2407 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2408 "mr 11,%1\n\t" \ 2409 "mr %0,3\n\t" \ 2410 "ld 2,-16(11)" /* restore tocptr */ \ 2411 : /*out*/ "=r" (_res) \ 2412 : /*in*/ "r" (&_argvec[2]) \ 2413 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2414 ); \ 2415 lval = (__typeof__(lval)) _res; \ 2416 } while (0) 2417 2418 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2419 arg7) \ 2420 do { \ 2421 volatile OrigFn _orig = (orig); \ 2422 volatile unsigned long _argvec[3+7]; \ 2423 volatile unsigned long _res; \ 2424 /* _argvec[0] holds current r2 across the call */ \ 2425 _argvec[1] = (unsigned long)_orig.r2; \ 2426 _argvec[2] = (unsigned long)_orig.nraddr; \ 2427 _argvec[2+1] = (unsigned long)arg1; \ 2428 _argvec[2+2] = (unsigned long)arg2; \ 2429 _argvec[2+3] = (unsigned long)arg3; \ 2430 _argvec[2+4] = (unsigned long)arg4; \ 2431 _argvec[2+5] = (unsigned long)arg5; \ 2432 _argvec[2+6] = (unsigned long)arg6; \ 2433 _argvec[2+7] = (unsigned long)arg7; \ 2434 __asm__ volatile( \ 2435 "mr 11,%1\n\t" \ 2436 "std 2,-16(11)\n\t" /* save tocptr */ \ 2437 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2438 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2439 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2440 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2441 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2442 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2443 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2444 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 2445 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2446 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2447 "mr 11,%1\n\t" \ 2448 "mr %0,3\n\t" \ 2449 "ld 2,-16(11)" /* restore tocptr */ \ 2450 : /*out*/ "=r" (_res) \ 2451 : /*in*/ "r" (&_argvec[2]) \ 2452 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2453 ); \ 2454 lval = (__typeof__(lval)) _res; \ 2455 } while (0) 2456 2457 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2458 arg7,arg8) \ 2459 do { \ 2460 volatile OrigFn _orig = (orig); \ 2461 volatile unsigned long _argvec[3+8]; \ 2462 volatile unsigned long _res; \ 2463 /* _argvec[0] holds current r2 across the call */ \ 2464 _argvec[1] = (unsigned long)_orig.r2; \ 2465 _argvec[2] = (unsigned long)_orig.nraddr; \ 2466 _argvec[2+1] = (unsigned long)arg1; \ 2467 _argvec[2+2] = (unsigned long)arg2; \ 2468 _argvec[2+3] = (unsigned long)arg3; \ 2469 _argvec[2+4] = (unsigned long)arg4; \ 2470 _argvec[2+5] = (unsigned long)arg5; \ 2471 _argvec[2+6] = (unsigned long)arg6; \ 2472 _argvec[2+7] = (unsigned long)arg7; \ 2473 _argvec[2+8] = (unsigned long)arg8; \ 2474 __asm__ volatile( \ 2475 "mr 11,%1\n\t" \ 2476 "std 2,-16(11)\n\t" /* save tocptr */ \ 2477 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2478 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2479 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2480 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2481 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2482 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2483 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2484 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 2485 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 2486 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2487 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2488 "mr 11,%1\n\t" \ 2489 "mr %0,3\n\t" \ 2490 "ld 2,-16(11)" /* restore tocptr */ \ 2491 : /*out*/ "=r" (_res) \ 2492 : /*in*/ "r" (&_argvec[2]) \ 2493 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2494 ); \ 2495 lval = (__typeof__(lval)) _res; \ 2496 } while (0) 2497 2498 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2499 arg7,arg8,arg9) \ 2500 do { \ 2501 volatile OrigFn _orig = (orig); \ 2502 volatile unsigned long _argvec[3+9]; \ 2503 volatile unsigned long _res; \ 2504 /* _argvec[0] holds current r2 across the call */ \ 2505 _argvec[1] = (unsigned long)_orig.r2; \ 2506 _argvec[2] = (unsigned long)_orig.nraddr; \ 2507 _argvec[2+1] = (unsigned long)arg1; \ 2508 _argvec[2+2] = (unsigned long)arg2; \ 2509 _argvec[2+3] = (unsigned long)arg3; \ 2510 _argvec[2+4] = (unsigned long)arg4; \ 2511 _argvec[2+5] = (unsigned long)arg5; \ 2512 _argvec[2+6] = (unsigned long)arg6; \ 2513 _argvec[2+7] = (unsigned long)arg7; \ 2514 _argvec[2+8] = (unsigned long)arg8; \ 2515 _argvec[2+9] = (unsigned long)arg9; \ 2516 __asm__ volatile( \ 2517 "mr 11,%1\n\t" \ 2518 "std 2,-16(11)\n\t" /* save tocptr */ \ 2519 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2520 "addi 1,1,-128\n\t" /* expand stack frame */ \ 2521 /* arg9 */ \ 2522 "ld 3,72(11)\n\t" \ 2523 "std 3,112(1)\n\t" \ 2524 /* args1-8 */ \ 2525 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2526 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2527 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2528 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2529 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2530 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2531 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 2532 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 2533 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2534 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2535 "mr 11,%1\n\t" \ 2536 "mr %0,3\n\t" \ 2537 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2538 "addi 1,1,128" /* restore frame */ \ 2539 : /*out*/ "=r" (_res) \ 2540 : /*in*/ "r" (&_argvec[2]) \ 2541 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2542 ); \ 2543 lval = (__typeof__(lval)) _res; \ 2544 } while (0) 2545 2546 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2547 arg7,arg8,arg9,arg10) \ 2548 do { \ 2549 volatile OrigFn _orig = (orig); \ 2550 volatile unsigned long _argvec[3+10]; \ 2551 volatile unsigned long _res; \ 2552 /* _argvec[0] holds current r2 across the call */ \ 2553 _argvec[1] = (unsigned long)_orig.r2; \ 2554 _argvec[2] = (unsigned long)_orig.nraddr; \ 2555 _argvec[2+1] = (unsigned long)arg1; \ 2556 _argvec[2+2] = (unsigned long)arg2; \ 2557 _argvec[2+3] = (unsigned long)arg3; \ 2558 _argvec[2+4] = (unsigned long)arg4; \ 2559 _argvec[2+5] = (unsigned long)arg5; \ 2560 _argvec[2+6] = (unsigned long)arg6; \ 2561 _argvec[2+7] = (unsigned long)arg7; \ 2562 _argvec[2+8] = (unsigned long)arg8; \ 2563 _argvec[2+9] = (unsigned long)arg9; \ 2564 _argvec[2+10] = (unsigned long)arg10; \ 2565 __asm__ volatile( \ 2566 "mr 11,%1\n\t" \ 2567 "std 2,-16(11)\n\t" /* save tocptr */ \ 2568 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2569 "addi 1,1,-128\n\t" /* expand stack frame */ \ 2570 /* arg10 */ \ 2571 "ld 3,80(11)\n\t" \ 2572 "std 3,120(1)\n\t" \ 2573 /* arg9 */ \ 2574 "ld 3,72(11)\n\t" \ 2575 "std 3,112(1)\n\t" \ 2576 /* args1-8 */ \ 2577 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2578 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2579 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2580 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2581 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2582 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2583 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 2584 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 2585 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2586 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2587 "mr 11,%1\n\t" \ 2588 "mr %0,3\n\t" \ 2589 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2590 "addi 1,1,128" /* restore frame */ \ 2591 : /*out*/ "=r" (_res) \ 2592 : /*in*/ "r" (&_argvec[2]) \ 2593 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2594 ); \ 2595 lval = (__typeof__(lval)) _res; \ 2596 } while (0) 2597 2598 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2599 arg7,arg8,arg9,arg10,arg11) \ 2600 do { \ 2601 volatile OrigFn _orig = (orig); \ 2602 volatile unsigned long _argvec[3+11]; \ 2603 volatile unsigned long _res; \ 2604 /* _argvec[0] holds current r2 across the call */ \ 2605 _argvec[1] = (unsigned long)_orig.r2; \ 2606 _argvec[2] = (unsigned long)_orig.nraddr; \ 2607 _argvec[2+1] = (unsigned long)arg1; \ 2608 _argvec[2+2] = (unsigned long)arg2; \ 2609 _argvec[2+3] = (unsigned long)arg3; \ 2610 _argvec[2+4] = (unsigned long)arg4; \ 2611 _argvec[2+5] = (unsigned long)arg5; \ 2612 _argvec[2+6] = (unsigned long)arg6; \ 2613 _argvec[2+7] = (unsigned long)arg7; \ 2614 _argvec[2+8] = (unsigned long)arg8; \ 2615 _argvec[2+9] = (unsigned long)arg9; \ 2616 _argvec[2+10] = (unsigned long)arg10; \ 2617 _argvec[2+11] = (unsigned long)arg11; \ 2618 __asm__ volatile( \ 2619 "mr 11,%1\n\t" \ 2620 "std 2,-16(11)\n\t" /* save tocptr */ \ 2621 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2622 "addi 1,1,-144\n\t" /* expand stack frame */ \ 2623 /* arg11 */ \ 2624 "ld 3,88(11)\n\t" \ 2625 "std 3,128(1)\n\t" \ 2626 /* arg10 */ \ 2627 "ld 3,80(11)\n\t" \ 2628 "std 3,120(1)\n\t" \ 2629 /* arg9 */ \ 2630 "ld 3,72(11)\n\t" \ 2631 "std 3,112(1)\n\t" \ 2632 /* args1-8 */ \ 2633 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2634 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2635 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2636 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2637 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2638 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2639 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 2640 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 2641 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2642 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2643 "mr 11,%1\n\t" \ 2644 "mr %0,3\n\t" \ 2645 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2646 "addi 1,1,144" /* restore frame */ \ 2647 : /*out*/ "=r" (_res) \ 2648 : /*in*/ "r" (&_argvec[2]) \ 2649 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2650 ); \ 2651 lval = (__typeof__(lval)) _res; \ 2652 } while (0) 2653 2654 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2655 arg7,arg8,arg9,arg10,arg11,arg12) \ 2656 do { \ 2657 volatile OrigFn _orig = (orig); \ 2658 volatile unsigned long _argvec[3+12]; \ 2659 volatile unsigned long _res; \ 2660 /* _argvec[0] holds current r2 across the call */ \ 2661 _argvec[1] = (unsigned long)_orig.r2; \ 2662 _argvec[2] = (unsigned long)_orig.nraddr; \ 2663 _argvec[2+1] = (unsigned long)arg1; \ 2664 _argvec[2+2] = (unsigned long)arg2; \ 2665 _argvec[2+3] = (unsigned long)arg3; \ 2666 _argvec[2+4] = (unsigned long)arg4; \ 2667 _argvec[2+5] = (unsigned long)arg5; \ 2668 _argvec[2+6] = (unsigned long)arg6; \ 2669 _argvec[2+7] = (unsigned long)arg7; \ 2670 _argvec[2+8] = (unsigned long)arg8; \ 2671 _argvec[2+9] = (unsigned long)arg9; \ 2672 _argvec[2+10] = (unsigned long)arg10; \ 2673 _argvec[2+11] = (unsigned long)arg11; \ 2674 _argvec[2+12] = (unsigned long)arg12; \ 2675 __asm__ volatile( \ 2676 "mr 11,%1\n\t" \ 2677 "std 2,-16(11)\n\t" /* save tocptr */ \ 2678 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2679 "addi 1,1,-144\n\t" /* expand stack frame */ \ 2680 /* arg12 */ \ 2681 "ld 3,96(11)\n\t" \ 2682 "std 3,136(1)\n\t" \ 2683 /* arg11 */ \ 2684 "ld 3,88(11)\n\t" \ 2685 "std 3,128(1)\n\t" \ 2686 /* arg10 */ \ 2687 "ld 3,80(11)\n\t" \ 2688 "std 3,120(1)\n\t" \ 2689 /* arg9 */ \ 2690 "ld 3,72(11)\n\t" \ 2691 "std 3,112(1)\n\t" \ 2692 /* args1-8 */ \ 2693 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2694 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2695 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2696 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2697 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2698 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2699 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 2700 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 2701 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2702 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2703 "mr 11,%1\n\t" \ 2704 "mr %0,3\n\t" \ 2705 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2706 "addi 1,1,144" /* restore frame */ \ 2707 : /*out*/ "=r" (_res) \ 2708 : /*in*/ "r" (&_argvec[2]) \ 2709 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2710 ); \ 2711 lval = (__typeof__(lval)) _res; \ 2712 } while (0) 2713 2714 #endif /* PLAT_ppc64_linux */ 2715 2716 /* ------------------------- arm-linux ------------------------- */ 2717 2718 #if defined(PLAT_arm_linux) 2719 2720 /* These regs are trashed by the hidden call. */ 2721 #define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14" 2722 2723 /* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned 2724 long) == 4. */ 2725 2726 #define CALL_FN_W_v(lval, orig) \ 2727 do { \ 2728 volatile OrigFn _orig = (orig); \ 2729 volatile unsigned long _argvec[1]; \ 2730 volatile unsigned long _res; \ 2731 _argvec[0] = (unsigned long)_orig.nraddr; \ 2732 __asm__ volatile( \ 2733 "ldr r4, [%1] \n\t" /* target->r4 */ \ 2734 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 2735 "mov %0, r0\n" \ 2736 : /*out*/ "=r" (_res) \ 2737 : /*in*/ "0" (&_argvec[0]) \ 2738 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2739 ); \ 2740 lval = (__typeof__(lval)) _res; \ 2741 } while (0) 2742 2743 #define CALL_FN_W_W(lval, orig, arg1) \ 2744 do { \ 2745 volatile OrigFn _orig = (orig); \ 2746 volatile unsigned long _argvec[2]; \ 2747 volatile unsigned long _res; \ 2748 _argvec[0] = (unsigned long)_orig.nraddr; \ 2749 _argvec[1] = (unsigned long)(arg1); \ 2750 __asm__ volatile( \ 2751 "ldr r0, [%1, #4] \n\t" \ 2752 "ldr r4, [%1] \n\t" /* target->r4 */ \ 2753 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 2754 "mov %0, r0\n" \ 2755 : /*out*/ "=r" (_res) \ 2756 : /*in*/ "0" (&_argvec[0]) \ 2757 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2758 ); \ 2759 lval = (__typeof__(lval)) _res; \ 2760 } while (0) 2761 2762 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 2763 do { \ 2764 volatile OrigFn _orig = (orig); \ 2765 volatile unsigned long _argvec[3]; \ 2766 volatile unsigned long _res; \ 2767 _argvec[0] = (unsigned long)_orig.nraddr; \ 2768 _argvec[1] = (unsigned long)(arg1); \ 2769 _argvec[2] = (unsigned long)(arg2); \ 2770 __asm__ volatile( \ 2771 "ldr r0, [%1, #4] \n\t" \ 2772 "ldr r1, [%1, #8] \n\t" \ 2773 "ldr r4, [%1] \n\t" /* target->r4 */ \ 2774 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 2775 "mov %0, r0\n" \ 2776 : /*out*/ "=r" (_res) \ 2777 : /*in*/ "0" (&_argvec[0]) \ 2778 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2779 ); \ 2780 lval = (__typeof__(lval)) _res; \ 2781 } while (0) 2782 2783 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 2784 do { \ 2785 volatile OrigFn _orig = (orig); \ 2786 volatile unsigned long _argvec[4]; \ 2787 volatile unsigned long _res; \ 2788 _argvec[0] = (unsigned long)_orig.nraddr; \ 2789 _argvec[1] = (unsigned long)(arg1); \ 2790 _argvec[2] = (unsigned long)(arg2); \ 2791 _argvec[3] = (unsigned long)(arg3); \ 2792 __asm__ volatile( \ 2793 "ldr r0, [%1, #4] \n\t" \ 2794 "ldr r1, [%1, #8] \n\t" \ 2795 "ldr r2, [%1, #12] \n\t" \ 2796 "ldr r4, [%1] \n\t" /* target->r4 */ \ 2797 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 2798 "mov %0, r0\n" \ 2799 : /*out*/ "=r" (_res) \ 2800 : /*in*/ "0" (&_argvec[0]) \ 2801 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2802 ); \ 2803 lval = (__typeof__(lval)) _res; \ 2804 } while (0) 2805 2806 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 2807 do { \ 2808 volatile OrigFn _orig = (orig); \ 2809 volatile unsigned long _argvec[5]; \ 2810 volatile unsigned long _res; \ 2811 _argvec[0] = (unsigned long)_orig.nraddr; \ 2812 _argvec[1] = (unsigned long)(arg1); \ 2813 _argvec[2] = (unsigned long)(arg2); \ 2814 _argvec[3] = (unsigned long)(arg3); \ 2815 _argvec[4] = (unsigned long)(arg4); \ 2816 __asm__ volatile( \ 2817 "ldr r0, [%1, #4] \n\t" \ 2818 "ldr r1, [%1, #8] \n\t" \ 2819 "ldr r2, [%1, #12] \n\t" \ 2820 "ldr r3, [%1, #16] \n\t" \ 2821 "ldr r4, [%1] \n\t" /* target->r4 */ \ 2822 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 2823 "mov %0, r0" \ 2824 : /*out*/ "=r" (_res) \ 2825 : /*in*/ "0" (&_argvec[0]) \ 2826 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2827 ); \ 2828 lval = (__typeof__(lval)) _res; \ 2829 } while (0) 2830 2831 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 2832 do { \ 2833 volatile OrigFn _orig = (orig); \ 2834 volatile unsigned long _argvec[6]; \ 2835 volatile unsigned long _res; \ 2836 _argvec[0] = (unsigned long)_orig.nraddr; \ 2837 _argvec[1] = (unsigned long)(arg1); \ 2838 _argvec[2] = (unsigned long)(arg2); \ 2839 _argvec[3] = (unsigned long)(arg3); \ 2840 _argvec[4] = (unsigned long)(arg4); \ 2841 _argvec[5] = (unsigned long)(arg5); \ 2842 __asm__ volatile( \ 2843 "ldr r0, [%1, #20] \n\t" \ 2844 "push {r0} \n\t" \ 2845 "ldr r0, [%1, #4] \n\t" \ 2846 "ldr r1, [%1, #8] \n\t" \ 2847 "ldr r2, [%1, #12] \n\t" \ 2848 "ldr r3, [%1, #16] \n\t" \ 2849 "ldr r4, [%1] \n\t" /* target->r4 */ \ 2850 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 2851 "add sp, sp, #4 \n\t" \ 2852 "mov %0, r0" \ 2853 : /*out*/ "=r" (_res) \ 2854 : /*in*/ "0" (&_argvec[0]) \ 2855 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2856 ); \ 2857 lval = (__typeof__(lval)) _res; \ 2858 } while (0) 2859 2860 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 2861 do { \ 2862 volatile OrigFn _orig = (orig); \ 2863 volatile unsigned long _argvec[7]; \ 2864 volatile unsigned long _res; \ 2865 _argvec[0] = (unsigned long)_orig.nraddr; \ 2866 _argvec[1] = (unsigned long)(arg1); \ 2867 _argvec[2] = (unsigned long)(arg2); \ 2868 _argvec[3] = (unsigned long)(arg3); \ 2869 _argvec[4] = (unsigned long)(arg4); \ 2870 _argvec[5] = (unsigned long)(arg5); \ 2871 _argvec[6] = (unsigned long)(arg6); \ 2872 __asm__ volatile( \ 2873 "ldr r0, [%1, #20] \n\t" \ 2874 "ldr r1, [%1, #24] \n\t" \ 2875 "push {r0, r1} \n\t" \ 2876 "ldr r0, [%1, #4] \n\t" \ 2877 "ldr r1, [%1, #8] \n\t" \ 2878 "ldr r2, [%1, #12] \n\t" \ 2879 "ldr r3, [%1, #16] \n\t" \ 2880 "ldr r4, [%1] \n\t" /* target->r4 */ \ 2881 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 2882 "add sp, sp, #8 \n\t" \ 2883 "mov %0, r0" \ 2884 : /*out*/ "=r" (_res) \ 2885 : /*in*/ "0" (&_argvec[0]) \ 2886 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2887 ); \ 2888 lval = (__typeof__(lval)) _res; \ 2889 } while (0) 2890 2891 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2892 arg7) \ 2893 do { \ 2894 volatile OrigFn _orig = (orig); \ 2895 volatile unsigned long _argvec[8]; \ 2896 volatile unsigned long _res; \ 2897 _argvec[0] = (unsigned long)_orig.nraddr; \ 2898 _argvec[1] = (unsigned long)(arg1); \ 2899 _argvec[2] = (unsigned long)(arg2); \ 2900 _argvec[3] = (unsigned long)(arg3); \ 2901 _argvec[4] = (unsigned long)(arg4); \ 2902 _argvec[5] = (unsigned long)(arg5); \ 2903 _argvec[6] = (unsigned long)(arg6); \ 2904 _argvec[7] = (unsigned long)(arg7); \ 2905 __asm__ volatile( \ 2906 "ldr r0, [%1, #20] \n\t" \ 2907 "ldr r1, [%1, #24] \n\t" \ 2908 "ldr r2, [%1, #28] \n\t" \ 2909 "push {r0, r1, r2} \n\t" \ 2910 "ldr r0, [%1, #4] \n\t" \ 2911 "ldr r1, [%1, #8] \n\t" \ 2912 "ldr r2, [%1, #12] \n\t" \ 2913 "ldr r3, [%1, #16] \n\t" \ 2914 "ldr r4, [%1] \n\t" /* target->r4 */ \ 2915 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 2916 "add sp, sp, #12 \n\t" \ 2917 "mov %0, r0" \ 2918 : /*out*/ "=r" (_res) \ 2919 : /*in*/ "0" (&_argvec[0]) \ 2920 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2921 ); \ 2922 lval = (__typeof__(lval)) _res; \ 2923 } while (0) 2924 2925 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2926 arg7,arg8) \ 2927 do { \ 2928 volatile OrigFn _orig = (orig); \ 2929 volatile unsigned long _argvec[9]; \ 2930 volatile unsigned long _res; \ 2931 _argvec[0] = (unsigned long)_orig.nraddr; \ 2932 _argvec[1] = (unsigned long)(arg1); \ 2933 _argvec[2] = (unsigned long)(arg2); \ 2934 _argvec[3] = (unsigned long)(arg3); \ 2935 _argvec[4] = (unsigned long)(arg4); \ 2936 _argvec[5] = (unsigned long)(arg5); \ 2937 _argvec[6] = (unsigned long)(arg6); \ 2938 _argvec[7] = (unsigned long)(arg7); \ 2939 _argvec[8] = (unsigned long)(arg8); \ 2940 __asm__ volatile( \ 2941 "ldr r0, [%1, #20] \n\t" \ 2942 "ldr r1, [%1, #24] \n\t" \ 2943 "ldr r2, [%1, #28] \n\t" \ 2944 "ldr r3, [%1, #32] \n\t" \ 2945 "push {r0, r1, r2, r3} \n\t" \ 2946 "ldr r0, [%1, #4] \n\t" \ 2947 "ldr r1, [%1, #8] \n\t" \ 2948 "ldr r2, [%1, #12] \n\t" \ 2949 "ldr r3, [%1, #16] \n\t" \ 2950 "ldr r4, [%1] \n\t" /* target->r4 */ \ 2951 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 2952 "add sp, sp, #16 \n\t" \ 2953 "mov %0, r0" \ 2954 : /*out*/ "=r" (_res) \ 2955 : /*in*/ "0" (&_argvec[0]) \ 2956 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2957 ); \ 2958 lval = (__typeof__(lval)) _res; \ 2959 } while (0) 2960 2961 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2962 arg7,arg8,arg9) \ 2963 do { \ 2964 volatile OrigFn _orig = (orig); \ 2965 volatile unsigned long _argvec[10]; \ 2966 volatile unsigned long _res; \ 2967 _argvec[0] = (unsigned long)_orig.nraddr; \ 2968 _argvec[1] = (unsigned long)(arg1); \ 2969 _argvec[2] = (unsigned long)(arg2); \ 2970 _argvec[3] = (unsigned long)(arg3); \ 2971 _argvec[4] = (unsigned long)(arg4); \ 2972 _argvec[5] = (unsigned long)(arg5); \ 2973 _argvec[6] = (unsigned long)(arg6); \ 2974 _argvec[7] = (unsigned long)(arg7); \ 2975 _argvec[8] = (unsigned long)(arg8); \ 2976 _argvec[9] = (unsigned long)(arg9); \ 2977 __asm__ volatile( \ 2978 "ldr r0, [%1, #20] \n\t" \ 2979 "ldr r1, [%1, #24] \n\t" \ 2980 "ldr r2, [%1, #28] \n\t" \ 2981 "ldr r3, [%1, #32] \n\t" \ 2982 "ldr r4, [%1, #36] \n\t" \ 2983 "push {r0, r1, r2, r3, r4} \n\t" \ 2984 "ldr r0, [%1, #4] \n\t" \ 2985 "ldr r1, [%1, #8] \n\t" \ 2986 "ldr r2, [%1, #12] \n\t" \ 2987 "ldr r3, [%1, #16] \n\t" \ 2988 "ldr r4, [%1] \n\t" /* target->r4 */ \ 2989 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 2990 "add sp, sp, #20 \n\t" \ 2991 "mov %0, r0" \ 2992 : /*out*/ "=r" (_res) \ 2993 : /*in*/ "0" (&_argvec[0]) \ 2994 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 2995 ); \ 2996 lval = (__typeof__(lval)) _res; \ 2997 } while (0) 2998 2999 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3000 arg7,arg8,arg9,arg10) \ 3001 do { \ 3002 volatile OrigFn _orig = (orig); \ 3003 volatile unsigned long _argvec[11]; \ 3004 volatile unsigned long _res; \ 3005 _argvec[0] = (unsigned long)_orig.nraddr; \ 3006 _argvec[1] = (unsigned long)(arg1); \ 3007 _argvec[2] = (unsigned long)(arg2); \ 3008 _argvec[3] = (unsigned long)(arg3); \ 3009 _argvec[4] = (unsigned long)(arg4); \ 3010 _argvec[5] = (unsigned long)(arg5); \ 3011 _argvec[6] = (unsigned long)(arg6); \ 3012 _argvec[7] = (unsigned long)(arg7); \ 3013 _argvec[8] = (unsigned long)(arg8); \ 3014 _argvec[9] = (unsigned long)(arg9); \ 3015 _argvec[10] = (unsigned long)(arg10); \ 3016 __asm__ volatile( \ 3017 "ldr r0, [%1, #40] \n\t" \ 3018 "push {r0} \n\t" \ 3019 "ldr r0, [%1, #20] \n\t" \ 3020 "ldr r1, [%1, #24] \n\t" \ 3021 "ldr r2, [%1, #28] \n\t" \ 3022 "ldr r3, [%1, #32] \n\t" \ 3023 "ldr r4, [%1, #36] \n\t" \ 3024 "push {r0, r1, r2, r3, r4} \n\t" \ 3025 "ldr r0, [%1, #4] \n\t" \ 3026 "ldr r1, [%1, #8] \n\t" \ 3027 "ldr r2, [%1, #12] \n\t" \ 3028 "ldr r3, [%1, #16] \n\t" \ 3029 "ldr r4, [%1] \n\t" /* target->r4 */ \ 3030 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 3031 "add sp, sp, #24 \n\t" \ 3032 "mov %0, r0" \ 3033 : /*out*/ "=r" (_res) \ 3034 : /*in*/ "0" (&_argvec[0]) \ 3035 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3036 ); \ 3037 lval = (__typeof__(lval)) _res; \ 3038 } while (0) 3039 3040 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ 3041 arg6,arg7,arg8,arg9,arg10, \ 3042 arg11) \ 3043 do { \ 3044 volatile OrigFn _orig = (orig); \ 3045 volatile unsigned long _argvec[12]; \ 3046 volatile unsigned long _res; \ 3047 _argvec[0] = (unsigned long)_orig.nraddr; \ 3048 _argvec[1] = (unsigned long)(arg1); \ 3049 _argvec[2] = (unsigned long)(arg2); \ 3050 _argvec[3] = (unsigned long)(arg3); \ 3051 _argvec[4] = (unsigned long)(arg4); \ 3052 _argvec[5] = (unsigned long)(arg5); \ 3053 _argvec[6] = (unsigned long)(arg6); \ 3054 _argvec[7] = (unsigned long)(arg7); \ 3055 _argvec[8] = (unsigned long)(arg8); \ 3056 _argvec[9] = (unsigned long)(arg9); \ 3057 _argvec[10] = (unsigned long)(arg10); \ 3058 _argvec[11] = (unsigned long)(arg11); \ 3059 __asm__ volatile( \ 3060 "ldr r0, [%1, #40] \n\t" \ 3061 "ldr r1, [%1, #44] \n\t" \ 3062 "push {r0, r1} \n\t" \ 3063 "ldr r0, [%1, #20] \n\t" \ 3064 "ldr r1, [%1, #24] \n\t" \ 3065 "ldr r2, [%1, #28] \n\t" \ 3066 "ldr r3, [%1, #32] \n\t" \ 3067 "ldr r4, [%1, #36] \n\t" \ 3068 "push {r0, r1, r2, r3, r4} \n\t" \ 3069 "ldr r0, [%1, #4] \n\t" \ 3070 "ldr r1, [%1, #8] \n\t" \ 3071 "ldr r2, [%1, #12] \n\t" \ 3072 "ldr r3, [%1, #16] \n\t" \ 3073 "ldr r4, [%1] \n\t" /* target->r4 */ \ 3074 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 3075 "add sp, sp, #28 \n\t" \ 3076 "mov %0, r0" \ 3077 : /*out*/ "=r" (_res) \ 3078 : /*in*/ "0" (&_argvec[0]) \ 3079 : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \ 3080 ); \ 3081 lval = (__typeof__(lval)) _res; \ 3082 } while (0) 3083 3084 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ 3085 arg6,arg7,arg8,arg9,arg10, \ 3086 arg11,arg12) \ 3087 do { \ 3088 volatile OrigFn _orig = (orig); \ 3089 volatile unsigned long _argvec[13]; \ 3090 volatile unsigned long _res; \ 3091 _argvec[0] = (unsigned long)_orig.nraddr; \ 3092 _argvec[1] = (unsigned long)(arg1); \ 3093 _argvec[2] = (unsigned long)(arg2); \ 3094 _argvec[3] = (unsigned long)(arg3); \ 3095 _argvec[4] = (unsigned long)(arg4); \ 3096 _argvec[5] = (unsigned long)(arg5); \ 3097 _argvec[6] = (unsigned long)(arg6); \ 3098 _argvec[7] = (unsigned long)(arg7); \ 3099 _argvec[8] = (unsigned long)(arg8); \ 3100 _argvec[9] = (unsigned long)(arg9); \ 3101 _argvec[10] = (unsigned long)(arg10); \ 3102 _argvec[11] = (unsigned long)(arg11); \ 3103 _argvec[12] = (unsigned long)(arg12); \ 3104 __asm__ volatile( \ 3105 "ldr r0, [%1, #40] \n\t" \ 3106 "ldr r1, [%1, #44] \n\t" \ 3107 "ldr r2, [%1, #48] \n\t" \ 3108 "push {r0, r1, r2} \n\t" \ 3109 "ldr r0, [%1, #20] \n\t" \ 3110 "ldr r1, [%1, #24] \n\t" \ 3111 "ldr r2, [%1, #28] \n\t" \ 3112 "ldr r3, [%1, #32] \n\t" \ 3113 "ldr r4, [%1, #36] \n\t" \ 3114 "push {r0, r1, r2, r3, r4} \n\t" \ 3115 "ldr r0, [%1, #4] \n\t" \ 3116 "ldr r1, [%1, #8] \n\t" \ 3117 "ldr r2, [%1, #12] \n\t" \ 3118 "ldr r3, [%1, #16] \n\t" \ 3119 "ldr r4, [%1] \n\t" /* target->r4 */ \ 3120 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 3121 "add sp, sp, #32 \n\t" \ 3122 "mov %0, r0" \ 3123 : /*out*/ "=r" (_res) \ 3124 : /*in*/ "0" (&_argvec[0]) \ 3125 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3126 ); \ 3127 lval = (__typeof__(lval)) _res; \ 3128 } while (0) 3129 3130 #endif /* PLAT_arm_linux */ 3131 3132 /* ------------------------ ppc32-aix5 ------------------------- */ 3133 3134 #if defined(PLAT_ppc32_aix5) 3135 3136 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ 3137 3138 /* These regs are trashed by the hidden call. */ 3139 #define __CALLER_SAVED_REGS \ 3140 "lr", "ctr", "xer", \ 3141 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ 3142 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ 3143 "r11", "r12", "r13" 3144 3145 /* Expand the stack frame, copying enough info that unwinding 3146 still works. Trashes r3. */ 3147 3148 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \ 3149 "addi 1,1,-" #_n_fr "\n\t" \ 3150 "lwz 3," #_n_fr "(1)\n\t" \ 3151 "stw 3,0(1)\n\t" 3152 3153 #define VG_CONTRACT_FRAME_BY(_n_fr) \ 3154 "addi 1,1," #_n_fr "\n\t" 3155 3156 /* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned 3157 long) == 4. */ 3158 3159 #define CALL_FN_W_v(lval, orig) \ 3160 do { \ 3161 volatile OrigFn _orig = (orig); \ 3162 volatile unsigned long _argvec[3+0]; \ 3163 volatile unsigned long _res; \ 3164 /* _argvec[0] holds current r2 across the call */ \ 3165 _argvec[1] = (unsigned long)_orig.r2; \ 3166 _argvec[2] = (unsigned long)_orig.nraddr; \ 3167 __asm__ volatile( \ 3168 "mr 11,%1\n\t" \ 3169 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3170 "stw 2,-8(11)\n\t" /* save tocptr */ \ 3171 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 3172 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 3173 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3174 "mr 11,%1\n\t" \ 3175 "mr %0,3\n\t" \ 3176 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 3177 VG_CONTRACT_FRAME_BY(512) \ 3178 : /*out*/ "=r" (_res) \ 3179 : /*in*/ "r" (&_argvec[2]) \ 3180 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3181 ); \ 3182 lval = (__typeof__(lval)) _res; \ 3183 } while (0) 3184 3185 #define CALL_FN_W_W(lval, orig, arg1) \ 3186 do { \ 3187 volatile OrigFn _orig = (orig); \ 3188 volatile unsigned long _argvec[3+1]; \ 3189 volatile unsigned long _res; \ 3190 /* _argvec[0] holds current r2 across the call */ \ 3191 _argvec[1] = (unsigned long)_orig.r2; \ 3192 _argvec[2] = (unsigned long)_orig.nraddr; \ 3193 _argvec[2+1] = (unsigned long)arg1; \ 3194 __asm__ volatile( \ 3195 "mr 11,%1\n\t" \ 3196 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3197 "stw 2,-8(11)\n\t" /* save tocptr */ \ 3198 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 3199 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 3200 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 3201 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3202 "mr 11,%1\n\t" \ 3203 "mr %0,3\n\t" \ 3204 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 3205 VG_CONTRACT_FRAME_BY(512) \ 3206 : /*out*/ "=r" (_res) \ 3207 : /*in*/ "r" (&_argvec[2]) \ 3208 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3209 ); \ 3210 lval = (__typeof__(lval)) _res; \ 3211 } while (0) 3212 3213 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 3214 do { \ 3215 volatile OrigFn _orig = (orig); \ 3216 volatile unsigned long _argvec[3+2]; \ 3217 volatile unsigned long _res; \ 3218 /* _argvec[0] holds current r2 across the call */ \ 3219 _argvec[1] = (unsigned long)_orig.r2; \ 3220 _argvec[2] = (unsigned long)_orig.nraddr; \ 3221 _argvec[2+1] = (unsigned long)arg1; \ 3222 _argvec[2+2] = (unsigned long)arg2; \ 3223 __asm__ volatile( \ 3224 "mr 11,%1\n\t" \ 3225 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3226 "stw 2,-8(11)\n\t" /* save tocptr */ \ 3227 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 3228 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 3229 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 3230 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 3231 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3232 "mr 11,%1\n\t" \ 3233 "mr %0,3\n\t" \ 3234 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 3235 VG_CONTRACT_FRAME_BY(512) \ 3236 : /*out*/ "=r" (_res) \ 3237 : /*in*/ "r" (&_argvec[2]) \ 3238 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3239 ); \ 3240 lval = (__typeof__(lval)) _res; \ 3241 } while (0) 3242 3243 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 3244 do { \ 3245 volatile OrigFn _orig = (orig); \ 3246 volatile unsigned long _argvec[3+3]; \ 3247 volatile unsigned long _res; \ 3248 /* _argvec[0] holds current r2 across the call */ \ 3249 _argvec[1] = (unsigned long)_orig.r2; \ 3250 _argvec[2] = (unsigned long)_orig.nraddr; \ 3251 _argvec[2+1] = (unsigned long)arg1; \ 3252 _argvec[2+2] = (unsigned long)arg2; \ 3253 _argvec[2+3] = (unsigned long)arg3; \ 3254 __asm__ volatile( \ 3255 "mr 11,%1\n\t" \ 3256 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3257 "stw 2,-8(11)\n\t" /* save tocptr */ \ 3258 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 3259 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 3260 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 3261 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 3262 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 3263 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3264 "mr 11,%1\n\t" \ 3265 "mr %0,3\n\t" \ 3266 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 3267 VG_CONTRACT_FRAME_BY(512) \ 3268 : /*out*/ "=r" (_res) \ 3269 : /*in*/ "r" (&_argvec[2]) \ 3270 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3271 ); \ 3272 lval = (__typeof__(lval)) _res; \ 3273 } while (0) 3274 3275 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 3276 do { \ 3277 volatile OrigFn _orig = (orig); \ 3278 volatile unsigned long _argvec[3+4]; \ 3279 volatile unsigned long _res; \ 3280 /* _argvec[0] holds current r2 across the call */ \ 3281 _argvec[1] = (unsigned long)_orig.r2; \ 3282 _argvec[2] = (unsigned long)_orig.nraddr; \ 3283 _argvec[2+1] = (unsigned long)arg1; \ 3284 _argvec[2+2] = (unsigned long)arg2; \ 3285 _argvec[2+3] = (unsigned long)arg3; \ 3286 _argvec[2+4] = (unsigned long)arg4; \ 3287 __asm__ volatile( \ 3288 "mr 11,%1\n\t" \ 3289 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3290 "stw 2,-8(11)\n\t" /* save tocptr */ \ 3291 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 3292 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 3293 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 3294 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 3295 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 3296 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 3297 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3298 "mr 11,%1\n\t" \ 3299 "mr %0,3\n\t" \ 3300 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 3301 VG_CONTRACT_FRAME_BY(512) \ 3302 : /*out*/ "=r" (_res) \ 3303 : /*in*/ "r" (&_argvec[2]) \ 3304 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3305 ); \ 3306 lval = (__typeof__(lval)) _res; \ 3307 } while (0) 3308 3309 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 3310 do { \ 3311 volatile OrigFn _orig = (orig); \ 3312 volatile unsigned long _argvec[3+5]; \ 3313 volatile unsigned long _res; \ 3314 /* _argvec[0] holds current r2 across the call */ \ 3315 _argvec[1] = (unsigned long)_orig.r2; \ 3316 _argvec[2] = (unsigned long)_orig.nraddr; \ 3317 _argvec[2+1] = (unsigned long)arg1; \ 3318 _argvec[2+2] = (unsigned long)arg2; \ 3319 _argvec[2+3] = (unsigned long)arg3; \ 3320 _argvec[2+4] = (unsigned long)arg4; \ 3321 _argvec[2+5] = (unsigned long)arg5; \ 3322 __asm__ volatile( \ 3323 "mr 11,%1\n\t" \ 3324 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3325 "stw 2,-8(11)\n\t" /* save tocptr */ \ 3326 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 3327 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 3328 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 3329 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 3330 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 3331 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 3332 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 3333 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3334 "mr 11,%1\n\t" \ 3335 "mr %0,3\n\t" \ 3336 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 3337 VG_CONTRACT_FRAME_BY(512) \ 3338 : /*out*/ "=r" (_res) \ 3339 : /*in*/ "r" (&_argvec[2]) \ 3340 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3341 ); \ 3342 lval = (__typeof__(lval)) _res; \ 3343 } while (0) 3344 3345 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 3346 do { \ 3347 volatile OrigFn _orig = (orig); \ 3348 volatile unsigned long _argvec[3+6]; \ 3349 volatile unsigned long _res; \ 3350 /* _argvec[0] holds current r2 across the call */ \ 3351 _argvec[1] = (unsigned long)_orig.r2; \ 3352 _argvec[2] = (unsigned long)_orig.nraddr; \ 3353 _argvec[2+1] = (unsigned long)arg1; \ 3354 _argvec[2+2] = (unsigned long)arg2; \ 3355 _argvec[2+3] = (unsigned long)arg3; \ 3356 _argvec[2+4] = (unsigned long)arg4; \ 3357 _argvec[2+5] = (unsigned long)arg5; \ 3358 _argvec[2+6] = (unsigned long)arg6; \ 3359 __asm__ volatile( \ 3360 "mr 11,%1\n\t" \ 3361 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3362 "stw 2,-8(11)\n\t" /* save tocptr */ \ 3363 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 3364 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 3365 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 3366 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 3367 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 3368 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 3369 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 3370 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 3371 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3372 "mr 11,%1\n\t" \ 3373 "mr %0,3\n\t" \ 3374 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 3375 VG_CONTRACT_FRAME_BY(512) \ 3376 : /*out*/ "=r" (_res) \ 3377 : /*in*/ "r" (&_argvec[2]) \ 3378 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3379 ); \ 3380 lval = (__typeof__(lval)) _res; \ 3381 } while (0) 3382 3383 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3384 arg7) \ 3385 do { \ 3386 volatile OrigFn _orig = (orig); \ 3387 volatile unsigned long _argvec[3+7]; \ 3388 volatile unsigned long _res; \ 3389 /* _argvec[0] holds current r2 across the call */ \ 3390 _argvec[1] = (unsigned long)_orig.r2; \ 3391 _argvec[2] = (unsigned long)_orig.nraddr; \ 3392 _argvec[2+1] = (unsigned long)arg1; \ 3393 _argvec[2+2] = (unsigned long)arg2; \ 3394 _argvec[2+3] = (unsigned long)arg3; \ 3395 _argvec[2+4] = (unsigned long)arg4; \ 3396 _argvec[2+5] = (unsigned long)arg5; \ 3397 _argvec[2+6] = (unsigned long)arg6; \ 3398 _argvec[2+7] = (unsigned long)arg7; \ 3399 __asm__ volatile( \ 3400 "mr 11,%1\n\t" \ 3401 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3402 "stw 2,-8(11)\n\t" /* save tocptr */ \ 3403 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 3404 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 3405 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 3406 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 3407 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 3408 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 3409 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 3410 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ 3411 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 3412 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3413 "mr 11,%1\n\t" \ 3414 "mr %0,3\n\t" \ 3415 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 3416 VG_CONTRACT_FRAME_BY(512) \ 3417 : /*out*/ "=r" (_res) \ 3418 : /*in*/ "r" (&_argvec[2]) \ 3419 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3420 ); \ 3421 lval = (__typeof__(lval)) _res; \ 3422 } while (0) 3423 3424 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3425 arg7,arg8) \ 3426 do { \ 3427 volatile OrigFn _orig = (orig); \ 3428 volatile unsigned long _argvec[3+8]; \ 3429 volatile unsigned long _res; \ 3430 /* _argvec[0] holds current r2 across the call */ \ 3431 _argvec[1] = (unsigned long)_orig.r2; \ 3432 _argvec[2] = (unsigned long)_orig.nraddr; \ 3433 _argvec[2+1] = (unsigned long)arg1; \ 3434 _argvec[2+2] = (unsigned long)arg2; \ 3435 _argvec[2+3] = (unsigned long)arg3; \ 3436 _argvec[2+4] = (unsigned long)arg4; \ 3437 _argvec[2+5] = (unsigned long)arg5; \ 3438 _argvec[2+6] = (unsigned long)arg6; \ 3439 _argvec[2+7] = (unsigned long)arg7; \ 3440 _argvec[2+8] = (unsigned long)arg8; \ 3441 __asm__ volatile( \ 3442 "mr 11,%1\n\t" \ 3443 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3444 "stw 2,-8(11)\n\t" /* save tocptr */ \ 3445 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 3446 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 3447 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 3448 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 3449 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 3450 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 3451 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 3452 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ 3453 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ 3454 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 3455 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3456 "mr 11,%1\n\t" \ 3457 "mr %0,3\n\t" \ 3458 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 3459 VG_CONTRACT_FRAME_BY(512) \ 3460 : /*out*/ "=r" (_res) \ 3461 : /*in*/ "r" (&_argvec[2]) \ 3462 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3463 ); \ 3464 lval = (__typeof__(lval)) _res; \ 3465 } while (0) 3466 3467 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3468 arg7,arg8,arg9) \ 3469 do { \ 3470 volatile OrigFn _orig = (orig); \ 3471 volatile unsigned long _argvec[3+9]; \ 3472 volatile unsigned long _res; \ 3473 /* _argvec[0] holds current r2 across the call */ \ 3474 _argvec[1] = (unsigned long)_orig.r2; \ 3475 _argvec[2] = (unsigned long)_orig.nraddr; \ 3476 _argvec[2+1] = (unsigned long)arg1; \ 3477 _argvec[2+2] = (unsigned long)arg2; \ 3478 _argvec[2+3] = (unsigned long)arg3; \ 3479 _argvec[2+4] = (unsigned long)arg4; \ 3480 _argvec[2+5] = (unsigned long)arg5; \ 3481 _argvec[2+6] = (unsigned long)arg6; \ 3482 _argvec[2+7] = (unsigned long)arg7; \ 3483 _argvec[2+8] = (unsigned long)arg8; \ 3484 _argvec[2+9] = (unsigned long)arg9; \ 3485 __asm__ volatile( \ 3486 "mr 11,%1\n\t" \ 3487 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3488 "stw 2,-8(11)\n\t" /* save tocptr */ \ 3489 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 3490 VG_EXPAND_FRAME_BY_trashes_r3(64) \ 3491 /* arg9 */ \ 3492 "lwz 3,36(11)\n\t" \ 3493 "stw 3,56(1)\n\t" \ 3494 /* args1-8 */ \ 3495 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 3496 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 3497 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 3498 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 3499 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 3500 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 3501 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ 3502 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ 3503 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 3504 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3505 "mr 11,%1\n\t" \ 3506 "mr %0,3\n\t" \ 3507 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 3508 VG_CONTRACT_FRAME_BY(64) \ 3509 VG_CONTRACT_FRAME_BY(512) \ 3510 : /*out*/ "=r" (_res) \ 3511 : /*in*/ "r" (&_argvec[2]) \ 3512 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3513 ); \ 3514 lval = (__typeof__(lval)) _res; \ 3515 } while (0) 3516 3517 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3518 arg7,arg8,arg9,arg10) \ 3519 do { \ 3520 volatile OrigFn _orig = (orig); \ 3521 volatile unsigned long _argvec[3+10]; \ 3522 volatile unsigned long _res; \ 3523 /* _argvec[0] holds current r2 across the call */ \ 3524 _argvec[1] = (unsigned long)_orig.r2; \ 3525 _argvec[2] = (unsigned long)_orig.nraddr; \ 3526 _argvec[2+1] = (unsigned long)arg1; \ 3527 _argvec[2+2] = (unsigned long)arg2; \ 3528 _argvec[2+3] = (unsigned long)arg3; \ 3529 _argvec[2+4] = (unsigned long)arg4; \ 3530 _argvec[2+5] = (unsigned long)arg5; \ 3531 _argvec[2+6] = (unsigned long)arg6; \ 3532 _argvec[2+7] = (unsigned long)arg7; \ 3533 _argvec[2+8] = (unsigned long)arg8; \ 3534 _argvec[2+9] = (unsigned long)arg9; \ 3535 _argvec[2+10] = (unsigned long)arg10; \ 3536 __asm__ volatile( \ 3537 "mr 11,%1\n\t" \ 3538 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3539 "stw 2,-8(11)\n\t" /* save tocptr */ \ 3540 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 3541 VG_EXPAND_FRAME_BY_trashes_r3(64) \ 3542 /* arg10 */ \ 3543 "lwz 3,40(11)\n\t" \ 3544 "stw 3,60(1)\n\t" \ 3545 /* arg9 */ \ 3546 "lwz 3,36(11)\n\t" \ 3547 "stw 3,56(1)\n\t" \ 3548 /* args1-8 */ \ 3549 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 3550 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 3551 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 3552 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 3553 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 3554 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 3555 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ 3556 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ 3557 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 3558 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3559 "mr 11,%1\n\t" \ 3560 "mr %0,3\n\t" \ 3561 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 3562 VG_CONTRACT_FRAME_BY(64) \ 3563 VG_CONTRACT_FRAME_BY(512) \ 3564 : /*out*/ "=r" (_res) \ 3565 : /*in*/ "r" (&_argvec[2]) \ 3566 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3567 ); \ 3568 lval = (__typeof__(lval)) _res; \ 3569 } while (0) 3570 3571 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3572 arg7,arg8,arg9,arg10,arg11) \ 3573 do { \ 3574 volatile OrigFn _orig = (orig); \ 3575 volatile unsigned long _argvec[3+11]; \ 3576 volatile unsigned long _res; \ 3577 /* _argvec[0] holds current r2 across the call */ \ 3578 _argvec[1] = (unsigned long)_orig.r2; \ 3579 _argvec[2] = (unsigned long)_orig.nraddr; \ 3580 _argvec[2+1] = (unsigned long)arg1; \ 3581 _argvec[2+2] = (unsigned long)arg2; \ 3582 _argvec[2+3] = (unsigned long)arg3; \ 3583 _argvec[2+4] = (unsigned long)arg4; \ 3584 _argvec[2+5] = (unsigned long)arg5; \ 3585 _argvec[2+6] = (unsigned long)arg6; \ 3586 _argvec[2+7] = (unsigned long)arg7; \ 3587 _argvec[2+8] = (unsigned long)arg8; \ 3588 _argvec[2+9] = (unsigned long)arg9; \ 3589 _argvec[2+10] = (unsigned long)arg10; \ 3590 _argvec[2+11] = (unsigned long)arg11; \ 3591 __asm__ volatile( \ 3592 "mr 11,%1\n\t" \ 3593 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3594 "stw 2,-8(11)\n\t" /* save tocptr */ \ 3595 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 3596 VG_EXPAND_FRAME_BY_trashes_r3(72) \ 3597 /* arg11 */ \ 3598 "lwz 3,44(11)\n\t" \ 3599 "stw 3,64(1)\n\t" \ 3600 /* arg10 */ \ 3601 "lwz 3,40(11)\n\t" \ 3602 "stw 3,60(1)\n\t" \ 3603 /* arg9 */ \ 3604 "lwz 3,36(11)\n\t" \ 3605 "stw 3,56(1)\n\t" \ 3606 /* args1-8 */ \ 3607 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 3608 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 3609 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 3610 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 3611 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 3612 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 3613 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ 3614 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ 3615 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 3616 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3617 "mr 11,%1\n\t" \ 3618 "mr %0,3\n\t" \ 3619 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 3620 VG_CONTRACT_FRAME_BY(72) \ 3621 VG_CONTRACT_FRAME_BY(512) \ 3622 : /*out*/ "=r" (_res) \ 3623 : /*in*/ "r" (&_argvec[2]) \ 3624 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3625 ); \ 3626 lval = (__typeof__(lval)) _res; \ 3627 } while (0) 3628 3629 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3630 arg7,arg8,arg9,arg10,arg11,arg12) \ 3631 do { \ 3632 volatile OrigFn _orig = (orig); \ 3633 volatile unsigned long _argvec[3+12]; \ 3634 volatile unsigned long _res; \ 3635 /* _argvec[0] holds current r2 across the call */ \ 3636 _argvec[1] = (unsigned long)_orig.r2; \ 3637 _argvec[2] = (unsigned long)_orig.nraddr; \ 3638 _argvec[2+1] = (unsigned long)arg1; \ 3639 _argvec[2+2] = (unsigned long)arg2; \ 3640 _argvec[2+3] = (unsigned long)arg3; \ 3641 _argvec[2+4] = (unsigned long)arg4; \ 3642 _argvec[2+5] = (unsigned long)arg5; \ 3643 _argvec[2+6] = (unsigned long)arg6; \ 3644 _argvec[2+7] = (unsigned long)arg7; \ 3645 _argvec[2+8] = (unsigned long)arg8; \ 3646 _argvec[2+9] = (unsigned long)arg9; \ 3647 _argvec[2+10] = (unsigned long)arg10; \ 3648 _argvec[2+11] = (unsigned long)arg11; \ 3649 _argvec[2+12] = (unsigned long)arg12; \ 3650 __asm__ volatile( \ 3651 "mr 11,%1\n\t" \ 3652 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3653 "stw 2,-8(11)\n\t" /* save tocptr */ \ 3654 "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ 3655 VG_EXPAND_FRAME_BY_trashes_r3(72) \ 3656 /* arg12 */ \ 3657 "lwz 3,48(11)\n\t" \ 3658 "stw 3,68(1)\n\t" \ 3659 /* arg11 */ \ 3660 "lwz 3,44(11)\n\t" \ 3661 "stw 3,64(1)\n\t" \ 3662 /* arg10 */ \ 3663 "lwz 3,40(11)\n\t" \ 3664 "stw 3,60(1)\n\t" \ 3665 /* arg9 */ \ 3666 "lwz 3,36(11)\n\t" \ 3667 "stw 3,56(1)\n\t" \ 3668 /* args1-8 */ \ 3669 "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ 3670 "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ 3671 "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ 3672 "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ 3673 "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ 3674 "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ 3675 "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ 3676 "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ 3677 "lwz 11, 0(11)\n\t" /* target->r11 */ \ 3678 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3679 "mr 11,%1\n\t" \ 3680 "mr %0,3\n\t" \ 3681 "lwz 2,-8(11)\n\t" /* restore tocptr */ \ 3682 VG_CONTRACT_FRAME_BY(72) \ 3683 VG_CONTRACT_FRAME_BY(512) \ 3684 : /*out*/ "=r" (_res) \ 3685 : /*in*/ "r" (&_argvec[2]) \ 3686 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3687 ); \ 3688 lval = (__typeof__(lval)) _res; \ 3689 } while (0) 3690 3691 #endif /* PLAT_ppc32_aix5 */ 3692 3693 /* ------------------------ ppc64-aix5 ------------------------- */ 3694 3695 #if defined(PLAT_ppc64_aix5) 3696 3697 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ 3698 3699 /* These regs are trashed by the hidden call. */ 3700 #define __CALLER_SAVED_REGS \ 3701 "lr", "ctr", "xer", \ 3702 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ 3703 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ 3704 "r11", "r12", "r13" 3705 3706 /* Expand the stack frame, copying enough info that unwinding 3707 still works. Trashes r3. */ 3708 3709 #define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \ 3710 "addi 1,1,-" #_n_fr "\n\t" \ 3711 "ld 3," #_n_fr "(1)\n\t" \ 3712 "std 3,0(1)\n\t" 3713 3714 #define VG_CONTRACT_FRAME_BY(_n_fr) \ 3715 "addi 1,1," #_n_fr "\n\t" 3716 3717 /* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned 3718 long) == 8. */ 3719 3720 #define CALL_FN_W_v(lval, orig) \ 3721 do { \ 3722 volatile OrigFn _orig = (orig); \ 3723 volatile unsigned long _argvec[3+0]; \ 3724 volatile unsigned long _res; \ 3725 /* _argvec[0] holds current r2 across the call */ \ 3726 _argvec[1] = (unsigned long)_orig.r2; \ 3727 _argvec[2] = (unsigned long)_orig.nraddr; \ 3728 __asm__ volatile( \ 3729 "mr 11,%1\n\t" \ 3730 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3731 "std 2,-16(11)\n\t" /* save tocptr */ \ 3732 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3733 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3734 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3735 "mr 11,%1\n\t" \ 3736 "mr %0,3\n\t" \ 3737 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3738 VG_CONTRACT_FRAME_BY(512) \ 3739 : /*out*/ "=r" (_res) \ 3740 : /*in*/ "r" (&_argvec[2]) \ 3741 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3742 ); \ 3743 lval = (__typeof__(lval)) _res; \ 3744 } while (0) 3745 3746 #define CALL_FN_W_W(lval, orig, arg1) \ 3747 do { \ 3748 volatile OrigFn _orig = (orig); \ 3749 volatile unsigned long _argvec[3+1]; \ 3750 volatile unsigned long _res; \ 3751 /* _argvec[0] holds current r2 across the call */ \ 3752 _argvec[1] = (unsigned long)_orig.r2; \ 3753 _argvec[2] = (unsigned long)_orig.nraddr; \ 3754 _argvec[2+1] = (unsigned long)arg1; \ 3755 __asm__ volatile( \ 3756 "mr 11,%1\n\t" \ 3757 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3758 "std 2,-16(11)\n\t" /* save tocptr */ \ 3759 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3760 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3761 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3762 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3763 "mr 11,%1\n\t" \ 3764 "mr %0,3\n\t" \ 3765 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3766 VG_CONTRACT_FRAME_BY(512) \ 3767 : /*out*/ "=r" (_res) \ 3768 : /*in*/ "r" (&_argvec[2]) \ 3769 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3770 ); \ 3771 lval = (__typeof__(lval)) _res; \ 3772 } while (0) 3773 3774 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 3775 do { \ 3776 volatile OrigFn _orig = (orig); \ 3777 volatile unsigned long _argvec[3+2]; \ 3778 volatile unsigned long _res; \ 3779 /* _argvec[0] holds current r2 across the call */ \ 3780 _argvec[1] = (unsigned long)_orig.r2; \ 3781 _argvec[2] = (unsigned long)_orig.nraddr; \ 3782 _argvec[2+1] = (unsigned long)arg1; \ 3783 _argvec[2+2] = (unsigned long)arg2; \ 3784 __asm__ volatile( \ 3785 "mr 11,%1\n\t" \ 3786 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3787 "std 2,-16(11)\n\t" /* save tocptr */ \ 3788 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3789 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3790 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3791 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3792 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3793 "mr 11,%1\n\t" \ 3794 "mr %0,3\n\t" \ 3795 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3796 VG_CONTRACT_FRAME_BY(512) \ 3797 : /*out*/ "=r" (_res) \ 3798 : /*in*/ "r" (&_argvec[2]) \ 3799 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3800 ); \ 3801 lval = (__typeof__(lval)) _res; \ 3802 } while (0) 3803 3804 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 3805 do { \ 3806 volatile OrigFn _orig = (orig); \ 3807 volatile unsigned long _argvec[3+3]; \ 3808 volatile unsigned long _res; \ 3809 /* _argvec[0] holds current r2 across the call */ \ 3810 _argvec[1] = (unsigned long)_orig.r2; \ 3811 _argvec[2] = (unsigned long)_orig.nraddr; \ 3812 _argvec[2+1] = (unsigned long)arg1; \ 3813 _argvec[2+2] = (unsigned long)arg2; \ 3814 _argvec[2+3] = (unsigned long)arg3; \ 3815 __asm__ volatile( \ 3816 "mr 11,%1\n\t" \ 3817 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3818 "std 2,-16(11)\n\t" /* save tocptr */ \ 3819 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3820 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3821 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3822 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 3823 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3824 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3825 "mr 11,%1\n\t" \ 3826 "mr %0,3\n\t" \ 3827 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3828 VG_CONTRACT_FRAME_BY(512) \ 3829 : /*out*/ "=r" (_res) \ 3830 : /*in*/ "r" (&_argvec[2]) \ 3831 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3832 ); \ 3833 lval = (__typeof__(lval)) _res; \ 3834 } while (0) 3835 3836 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 3837 do { \ 3838 volatile OrigFn _orig = (orig); \ 3839 volatile unsigned long _argvec[3+4]; \ 3840 volatile unsigned long _res; \ 3841 /* _argvec[0] holds current r2 across the call */ \ 3842 _argvec[1] = (unsigned long)_orig.r2; \ 3843 _argvec[2] = (unsigned long)_orig.nraddr; \ 3844 _argvec[2+1] = (unsigned long)arg1; \ 3845 _argvec[2+2] = (unsigned long)arg2; \ 3846 _argvec[2+3] = (unsigned long)arg3; \ 3847 _argvec[2+4] = (unsigned long)arg4; \ 3848 __asm__ volatile( \ 3849 "mr 11,%1\n\t" \ 3850 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3851 "std 2,-16(11)\n\t" /* save tocptr */ \ 3852 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3853 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3854 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3855 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 3856 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 3857 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3858 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3859 "mr 11,%1\n\t" \ 3860 "mr %0,3\n\t" \ 3861 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3862 VG_CONTRACT_FRAME_BY(512) \ 3863 : /*out*/ "=r" (_res) \ 3864 : /*in*/ "r" (&_argvec[2]) \ 3865 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3866 ); \ 3867 lval = (__typeof__(lval)) _res; \ 3868 } while (0) 3869 3870 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 3871 do { \ 3872 volatile OrigFn _orig = (orig); \ 3873 volatile unsigned long _argvec[3+5]; \ 3874 volatile unsigned long _res; \ 3875 /* _argvec[0] holds current r2 across the call */ \ 3876 _argvec[1] = (unsigned long)_orig.r2; \ 3877 _argvec[2] = (unsigned long)_orig.nraddr; \ 3878 _argvec[2+1] = (unsigned long)arg1; \ 3879 _argvec[2+2] = (unsigned long)arg2; \ 3880 _argvec[2+3] = (unsigned long)arg3; \ 3881 _argvec[2+4] = (unsigned long)arg4; \ 3882 _argvec[2+5] = (unsigned long)arg5; \ 3883 __asm__ volatile( \ 3884 "mr 11,%1\n\t" \ 3885 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3886 "std 2,-16(11)\n\t" /* save tocptr */ \ 3887 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3888 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3889 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3890 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 3891 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 3892 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 3893 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3894 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3895 "mr 11,%1\n\t" \ 3896 "mr %0,3\n\t" \ 3897 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3898 VG_CONTRACT_FRAME_BY(512) \ 3899 : /*out*/ "=r" (_res) \ 3900 : /*in*/ "r" (&_argvec[2]) \ 3901 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3902 ); \ 3903 lval = (__typeof__(lval)) _res; \ 3904 } while (0) 3905 3906 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 3907 do { \ 3908 volatile OrigFn _orig = (orig); \ 3909 volatile unsigned long _argvec[3+6]; \ 3910 volatile unsigned long _res; \ 3911 /* _argvec[0] holds current r2 across the call */ \ 3912 _argvec[1] = (unsigned long)_orig.r2; \ 3913 _argvec[2] = (unsigned long)_orig.nraddr; \ 3914 _argvec[2+1] = (unsigned long)arg1; \ 3915 _argvec[2+2] = (unsigned long)arg2; \ 3916 _argvec[2+3] = (unsigned long)arg3; \ 3917 _argvec[2+4] = (unsigned long)arg4; \ 3918 _argvec[2+5] = (unsigned long)arg5; \ 3919 _argvec[2+6] = (unsigned long)arg6; \ 3920 __asm__ volatile( \ 3921 "mr 11,%1\n\t" \ 3922 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3923 "std 2,-16(11)\n\t" /* save tocptr */ \ 3924 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3925 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3926 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3927 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 3928 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 3929 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 3930 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 3931 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3932 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3933 "mr 11,%1\n\t" \ 3934 "mr %0,3\n\t" \ 3935 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3936 VG_CONTRACT_FRAME_BY(512) \ 3937 : /*out*/ "=r" (_res) \ 3938 : /*in*/ "r" (&_argvec[2]) \ 3939 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3940 ); \ 3941 lval = (__typeof__(lval)) _res; \ 3942 } while (0) 3943 3944 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3945 arg7) \ 3946 do { \ 3947 volatile OrigFn _orig = (orig); \ 3948 volatile unsigned long _argvec[3+7]; \ 3949 volatile unsigned long _res; \ 3950 /* _argvec[0] holds current r2 across the call */ \ 3951 _argvec[1] = (unsigned long)_orig.r2; \ 3952 _argvec[2] = (unsigned long)_orig.nraddr; \ 3953 _argvec[2+1] = (unsigned long)arg1; \ 3954 _argvec[2+2] = (unsigned long)arg2; \ 3955 _argvec[2+3] = (unsigned long)arg3; \ 3956 _argvec[2+4] = (unsigned long)arg4; \ 3957 _argvec[2+5] = (unsigned long)arg5; \ 3958 _argvec[2+6] = (unsigned long)arg6; \ 3959 _argvec[2+7] = (unsigned long)arg7; \ 3960 __asm__ volatile( \ 3961 "mr 11,%1\n\t" \ 3962 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 3963 "std 2,-16(11)\n\t" /* save tocptr */ \ 3964 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3965 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3966 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3967 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 3968 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 3969 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 3970 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 3971 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 3972 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3973 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3974 "mr 11,%1\n\t" \ 3975 "mr %0,3\n\t" \ 3976 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3977 VG_CONTRACT_FRAME_BY(512) \ 3978 : /*out*/ "=r" (_res) \ 3979 : /*in*/ "r" (&_argvec[2]) \ 3980 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 3981 ); \ 3982 lval = (__typeof__(lval)) _res; \ 3983 } while (0) 3984 3985 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3986 arg7,arg8) \ 3987 do { \ 3988 volatile OrigFn _orig = (orig); \ 3989 volatile unsigned long _argvec[3+8]; \ 3990 volatile unsigned long _res; \ 3991 /* _argvec[0] holds current r2 across the call */ \ 3992 _argvec[1] = (unsigned long)_orig.r2; \ 3993 _argvec[2] = (unsigned long)_orig.nraddr; \ 3994 _argvec[2+1] = (unsigned long)arg1; \ 3995 _argvec[2+2] = (unsigned long)arg2; \ 3996 _argvec[2+3] = (unsigned long)arg3; \ 3997 _argvec[2+4] = (unsigned long)arg4; \ 3998 _argvec[2+5] = (unsigned long)arg5; \ 3999 _argvec[2+6] = (unsigned long)arg6; \ 4000 _argvec[2+7] = (unsigned long)arg7; \ 4001 _argvec[2+8] = (unsigned long)arg8; \ 4002 __asm__ volatile( \ 4003 "mr 11,%1\n\t" \ 4004 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 4005 "std 2,-16(11)\n\t" /* save tocptr */ \ 4006 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 4007 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 4008 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 4009 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 4010 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 4011 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 4012 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 4013 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 4014 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 4015 "ld 11, 0(11)\n\t" /* target->r11 */ \ 4016 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 4017 "mr 11,%1\n\t" \ 4018 "mr %0,3\n\t" \ 4019 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 4020 VG_CONTRACT_FRAME_BY(512) \ 4021 : /*out*/ "=r" (_res) \ 4022 : /*in*/ "r" (&_argvec[2]) \ 4023 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 4024 ); \ 4025 lval = (__typeof__(lval)) _res; \ 4026 } while (0) 4027 4028 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 4029 arg7,arg8,arg9) \ 4030 do { \ 4031 volatile OrigFn _orig = (orig); \ 4032 volatile unsigned long _argvec[3+9]; \ 4033 volatile unsigned long _res; \ 4034 /* _argvec[0] holds current r2 across the call */ \ 4035 _argvec[1] = (unsigned long)_orig.r2; \ 4036 _argvec[2] = (unsigned long)_orig.nraddr; \ 4037 _argvec[2+1] = (unsigned long)arg1; \ 4038 _argvec[2+2] = (unsigned long)arg2; \ 4039 _argvec[2+3] = (unsigned long)arg3; \ 4040 _argvec[2+4] = (unsigned long)arg4; \ 4041 _argvec[2+5] = (unsigned long)arg5; \ 4042 _argvec[2+6] = (unsigned long)arg6; \ 4043 _argvec[2+7] = (unsigned long)arg7; \ 4044 _argvec[2+8] = (unsigned long)arg8; \ 4045 _argvec[2+9] = (unsigned long)arg9; \ 4046 __asm__ volatile( \ 4047 "mr 11,%1\n\t" \ 4048 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 4049 "std 2,-16(11)\n\t" /* save tocptr */ \ 4050 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 4051 VG_EXPAND_FRAME_BY_trashes_r3(128) \ 4052 /* arg9 */ \ 4053 "ld 3,72(11)\n\t" \ 4054 "std 3,112(1)\n\t" \ 4055 /* args1-8 */ \ 4056 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 4057 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 4058 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 4059 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 4060 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 4061 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 4062 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 4063 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 4064 "ld 11, 0(11)\n\t" /* target->r11 */ \ 4065 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 4066 "mr 11,%1\n\t" \ 4067 "mr %0,3\n\t" \ 4068 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 4069 VG_CONTRACT_FRAME_BY(128) \ 4070 VG_CONTRACT_FRAME_BY(512) \ 4071 : /*out*/ "=r" (_res) \ 4072 : /*in*/ "r" (&_argvec[2]) \ 4073 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 4074 ); \ 4075 lval = (__typeof__(lval)) _res; \ 4076 } while (0) 4077 4078 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 4079 arg7,arg8,arg9,arg10) \ 4080 do { \ 4081 volatile OrigFn _orig = (orig); \ 4082 volatile unsigned long _argvec[3+10]; \ 4083 volatile unsigned long _res; \ 4084 /* _argvec[0] holds current r2 across the call */ \ 4085 _argvec[1] = (unsigned long)_orig.r2; \ 4086 _argvec[2] = (unsigned long)_orig.nraddr; \ 4087 _argvec[2+1] = (unsigned long)arg1; \ 4088 _argvec[2+2] = (unsigned long)arg2; \ 4089 _argvec[2+3] = (unsigned long)arg3; \ 4090 _argvec[2+4] = (unsigned long)arg4; \ 4091 _argvec[2+5] = (unsigned long)arg5; \ 4092 _argvec[2+6] = (unsigned long)arg6; \ 4093 _argvec[2+7] = (unsigned long)arg7; \ 4094 _argvec[2+8] = (unsigned long)arg8; \ 4095 _argvec[2+9] = (unsigned long)arg9; \ 4096 _argvec[2+10] = (unsigned long)arg10; \ 4097 __asm__ volatile( \ 4098 "mr 11,%1\n\t" \ 4099 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 4100 "std 2,-16(11)\n\t" /* save tocptr */ \ 4101 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 4102 VG_EXPAND_FRAME_BY_trashes_r3(128) \ 4103 /* arg10 */ \ 4104 "ld 3,80(11)\n\t" \ 4105 "std 3,120(1)\n\t" \ 4106 /* arg9 */ \ 4107 "ld 3,72(11)\n\t" \ 4108 "std 3,112(1)\n\t" \ 4109 /* args1-8 */ \ 4110 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 4111 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 4112 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 4113 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 4114 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 4115 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 4116 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 4117 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 4118 "ld 11, 0(11)\n\t" /* target->r11 */ \ 4119 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 4120 "mr 11,%1\n\t" \ 4121 "mr %0,3\n\t" \ 4122 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 4123 VG_CONTRACT_FRAME_BY(128) \ 4124 VG_CONTRACT_FRAME_BY(512) \ 4125 : /*out*/ "=r" (_res) \ 4126 : /*in*/ "r" (&_argvec[2]) \ 4127 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 4128 ); \ 4129 lval = (__typeof__(lval)) _res; \ 4130 } while (0) 4131 4132 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 4133 arg7,arg8,arg9,arg10,arg11) \ 4134 do { \ 4135 volatile OrigFn _orig = (orig); \ 4136 volatile unsigned long _argvec[3+11]; \ 4137 volatile unsigned long _res; \ 4138 /* _argvec[0] holds current r2 across the call */ \ 4139 _argvec[1] = (unsigned long)_orig.r2; \ 4140 _argvec[2] = (unsigned long)_orig.nraddr; \ 4141 _argvec[2+1] = (unsigned long)arg1; \ 4142 _argvec[2+2] = (unsigned long)arg2; \ 4143 _argvec[2+3] = (unsigned long)arg3; \ 4144 _argvec[2+4] = (unsigned long)arg4; \ 4145 _argvec[2+5] = (unsigned long)arg5; \ 4146 _argvec[2+6] = (unsigned long)arg6; \ 4147 _argvec[2+7] = (unsigned long)arg7; \ 4148 _argvec[2+8] = (unsigned long)arg8; \ 4149 _argvec[2+9] = (unsigned long)arg9; \ 4150 _argvec[2+10] = (unsigned long)arg10; \ 4151 _argvec[2+11] = (unsigned long)arg11; \ 4152 __asm__ volatile( \ 4153 "mr 11,%1\n\t" \ 4154 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 4155 "std 2,-16(11)\n\t" /* save tocptr */ \ 4156 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 4157 VG_EXPAND_FRAME_BY_trashes_r3(144) \ 4158 /* arg11 */ \ 4159 "ld 3,88(11)\n\t" \ 4160 "std 3,128(1)\n\t" \ 4161 /* arg10 */ \ 4162 "ld 3,80(11)\n\t" \ 4163 "std 3,120(1)\n\t" \ 4164 /* arg9 */ \ 4165 "ld 3,72(11)\n\t" \ 4166 "std 3,112(1)\n\t" \ 4167 /* args1-8 */ \ 4168 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 4169 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 4170 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 4171 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 4172 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 4173 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 4174 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 4175 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 4176 "ld 11, 0(11)\n\t" /* target->r11 */ \ 4177 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 4178 "mr 11,%1\n\t" \ 4179 "mr %0,3\n\t" \ 4180 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 4181 VG_CONTRACT_FRAME_BY(144) \ 4182 VG_CONTRACT_FRAME_BY(512) \ 4183 : /*out*/ "=r" (_res) \ 4184 : /*in*/ "r" (&_argvec[2]) \ 4185 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 4186 ); \ 4187 lval = (__typeof__(lval)) _res; \ 4188 } while (0) 4189 4190 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 4191 arg7,arg8,arg9,arg10,arg11,arg12) \ 4192 do { \ 4193 volatile OrigFn _orig = (orig); \ 4194 volatile unsigned long _argvec[3+12]; \ 4195 volatile unsigned long _res; \ 4196 /* _argvec[0] holds current r2 across the call */ \ 4197 _argvec[1] = (unsigned long)_orig.r2; \ 4198 _argvec[2] = (unsigned long)_orig.nraddr; \ 4199 _argvec[2+1] = (unsigned long)arg1; \ 4200 _argvec[2+2] = (unsigned long)arg2; \ 4201 _argvec[2+3] = (unsigned long)arg3; \ 4202 _argvec[2+4] = (unsigned long)arg4; \ 4203 _argvec[2+5] = (unsigned long)arg5; \ 4204 _argvec[2+6] = (unsigned long)arg6; \ 4205 _argvec[2+7] = (unsigned long)arg7; \ 4206 _argvec[2+8] = (unsigned long)arg8; \ 4207 _argvec[2+9] = (unsigned long)arg9; \ 4208 _argvec[2+10] = (unsigned long)arg10; \ 4209 _argvec[2+11] = (unsigned long)arg11; \ 4210 _argvec[2+12] = (unsigned long)arg12; \ 4211 __asm__ volatile( \ 4212 "mr 11,%1\n\t" \ 4213 VG_EXPAND_FRAME_BY_trashes_r3(512) \ 4214 "std 2,-16(11)\n\t" /* save tocptr */ \ 4215 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 4216 VG_EXPAND_FRAME_BY_trashes_r3(144) \ 4217 /* arg12 */ \ 4218 "ld 3,96(11)\n\t" \ 4219 "std 3,136(1)\n\t" \ 4220 /* arg11 */ \ 4221 "ld 3,88(11)\n\t" \ 4222 "std 3,128(1)\n\t" \ 4223 /* arg10 */ \ 4224 "ld 3,80(11)\n\t" \ 4225 "std 3,120(1)\n\t" \ 4226 /* arg9 */ \ 4227 "ld 3,72(11)\n\t" \ 4228 "std 3,112(1)\n\t" \ 4229 /* args1-8 */ \ 4230 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 4231 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 4232 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 4233 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 4234 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 4235 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 4236 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 4237 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 4238 "ld 11, 0(11)\n\t" /* target->r11 */ \ 4239 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 4240 "mr 11,%1\n\t" \ 4241 "mr %0,3\n\t" \ 4242 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 4243 VG_CONTRACT_FRAME_BY(144) \ 4244 VG_CONTRACT_FRAME_BY(512) \ 4245 : /*out*/ "=r" (_res) \ 4246 : /*in*/ "r" (&_argvec[2]) \ 4247 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ 4248 ); \ 4249 lval = (__typeof__(lval)) _res; \ 4250 } while (0) 4251 4252 #endif /* PLAT_ppc64_aix5 */ 4253 4254 4255 /* ------------------------------------------------------------------ */ 4256 /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */ 4257 /* */ 4258 /* ------------------------------------------------------------------ */ 4259 4260 /* Some request codes. There are many more of these, but most are not 4261 exposed to end-user view. These are the public ones, all of the 4262 form 0x1000 + small_number. 4263 4264 Core ones are in the range 0x00000000--0x0000ffff. The non-public 4265 ones start at 0x2000. 4266 */ 4267 4268 /* These macros are used by tools -- they must be public, but don't 4269 embed them into other programs. */ 4270 #define VG_USERREQ_TOOL_BASE(a,b) \ 4271 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16)) 4272 #define VG_IS_TOOL_USERREQ(a, b, v) \ 4273 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000)) 4274 4275 /* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! 4276 This enum comprises an ABI exported by Valgrind to programs 4277 which use client requests. DO NOT CHANGE THE ORDER OF THESE 4278 ENTRIES, NOR DELETE ANY -- add new ones at the end. */ 4279 typedef 4280 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001, 4281 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002, 4282 4283 /* These allow any function to be called from the simulated 4284 CPU but run on the real CPU. Nb: the first arg passed to 4285 the function is always the ThreadId of the running 4286 thread! So CLIENT_CALL0 actually requires a 1 arg 4287 function, etc. */ 4288 VG_USERREQ__CLIENT_CALL0 = 0x1101, 4289 VG_USERREQ__CLIENT_CALL1 = 0x1102, 4290 VG_USERREQ__CLIENT_CALL2 = 0x1103, 4291 VG_USERREQ__CLIENT_CALL3 = 0x1104, 4292 4293 /* Can be useful in regression testing suites -- eg. can 4294 send Valgrind's output to /dev/null and still count 4295 errors. */ 4296 VG_USERREQ__COUNT_ERRORS = 0x1201, 4297 4298 /* These are useful and can be interpreted by any tool that 4299 tracks malloc() et al, by using vg_replace_malloc.c. */ 4300 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301, 4301 VG_USERREQ__FREELIKE_BLOCK = 0x1302, 4302 /* Memory pool support. */ 4303 VG_USERREQ__CREATE_MEMPOOL = 0x1303, 4304 VG_USERREQ__DESTROY_MEMPOOL = 0x1304, 4305 VG_USERREQ__MEMPOOL_ALLOC = 0x1305, 4306 VG_USERREQ__MEMPOOL_FREE = 0x1306, 4307 VG_USERREQ__MEMPOOL_TRIM = 0x1307, 4308 VG_USERREQ__MOVE_MEMPOOL = 0x1308, 4309 VG_USERREQ__MEMPOOL_CHANGE = 0x1309, 4310 VG_USERREQ__MEMPOOL_EXISTS = 0x130a, 4311 4312 /* Allow printfs to valgrind log. */ 4313 /* The first two pass the va_list argument by value, which 4314 assumes it is the same size as or smaller than a UWord, 4315 which generally isn't the case. Hence are deprecated. 4316 The second two pass the vargs by reference and so are 4317 immune to this problem. */ 4318 /* both :: char* fmt, va_list vargs (DEPRECATED) */ 4319 VG_USERREQ__PRINTF = 0x1401, 4320 VG_USERREQ__PRINTF_BACKTRACE = 0x1402, 4321 /* both :: char* fmt, va_list* vargs */ 4322 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403, 4323 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404, 4324 4325 /* Stack support. */ 4326 VG_USERREQ__STACK_REGISTER = 0x1501, 4327 VG_USERREQ__STACK_DEREGISTER = 0x1502, 4328 VG_USERREQ__STACK_CHANGE = 0x1503, 4329 4330 /* Wine support */ 4331 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601, 4332 4333 /* Querying of debug info. */ 4334 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701 4335 } Vg_ClientRequest; 4336 4337 #if !defined(__GNUC__) 4338 # define __extension__ /* */ 4339 #endif 4340 4341 4342 /* 4343 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind 4344 * client request and whose value equals the client request result. 4345 */ 4346 4347 #if defined(NVALGRIND) 4348 4349 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ 4350 _zzq_default, _zzq_request, \ 4351 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 4352 (_zzq_default) 4353 4354 #else /*defined(NVALGRIND)*/ 4355 4356 #if defined(_MSC_VER) 4357 4358 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ 4359 _zzq_default, _zzq_request, \ 4360 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 4361 (vg_VALGRIND_DO_CLIENT_REQUEST_EXPR((uintptr_t)(_zzq_default), \ 4362 (_zzq_request), (uintptr_t)(_zzq_arg1), (uintptr_t)(_zzq_arg2), \ 4363 (uintptr_t)(_zzq_arg3), (uintptr_t)(_zzq_arg4), \ 4364 (uintptr_t)(_zzq_arg5))) 4365 4366 static __inline unsigned 4367 vg_VALGRIND_DO_CLIENT_REQUEST_EXPR(uintptr_t _zzq_default, 4368 unsigned _zzq_request, uintptr_t _zzq_arg1, 4369 uintptr_t _zzq_arg2, uintptr_t _zzq_arg3, 4370 uintptr_t _zzq_arg4, uintptr_t _zzq_arg5) 4371 { 4372 unsigned _zzq_rlval; 4373 VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request, 4374 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5); 4375 return _zzq_rlval; 4376 } 4377 4378 #else /*defined(_MSC_VER)*/ 4379 4380 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ 4381 _zzq_default, _zzq_request, \ 4382 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 4383 (__extension__({unsigned int _zzq_rlval; \ 4384 VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request, \ 4385 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 4386 _zzq_rlval; \ 4387 })) 4388 4389 #endif /*defined(_MSC_VER)*/ 4390 4391 #endif /*defined(NVALGRIND)*/ 4392 4393 4394 /* Returns the number of Valgrinds this code is running under. That 4395 is, 0 if running natively, 1 if running under Valgrind, 2 if 4396 running under Valgrind which is running under another Valgrind, 4397 etc. */ 4398 #define RUNNING_ON_VALGRIND \ 4399 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \ 4400 VG_USERREQ__RUNNING_ON_VALGRIND, \ 4401 0, 0, 0, 0, 0) \ 4402 4403 4404 /* Discard translation of code in the range [_qzz_addr .. _qzz_addr + 4405 _qzz_len - 1]. Useful if you are debugging a JITter or some such, 4406 since it provides a way to make sure valgrind will retranslate the 4407 invalidated area. Returns no value. */ 4408 #define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \ 4409 {unsigned int _qzz_res; \ 4410 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 4411 VG_USERREQ__DISCARD_TRANSLATIONS, \ 4412 _qzz_addr, _qzz_len, 0, 0, 0); \ 4413 } 4414 4415 4416 /* These requests are for getting Valgrind itself to print something. 4417 Possibly with a backtrace. This is a really ugly hack. The return value 4418 is the number of characters printed, excluding the "**<pid>** " part at the 4419 start and the backtrace (if present). */ 4420 4421 #if defined(NVALGRIND) 4422 4423 # define VALGRIND_PRINTF(...) 4424 # define VALGRIND_PRINTF_BACKTRACE(...) 4425 4426 #else /* NVALGRIND */ 4427 4428 #if !defined(_MSC_VER) 4429 /* Modern GCC will optimize the static routine out if unused, 4430 and unused attribute will shut down warnings about it. */ 4431 static int VALGRIND_PRINTF(const char *format, ...) 4432 __attribute__((format(__printf__, 1, 2), __unused__)); 4433 #endif 4434 static int 4435 #if defined(_MSC_VER) 4436 __inline 4437 #endif 4438 VALGRIND_PRINTF(const char *format, ...) 4439 { 4440 unsigned long _qzz_res; 4441 va_list vargs; 4442 va_start(vargs, format); 4443 #if defined(_MSC_VER) 4444 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, 4445 VG_USERREQ__PRINTF_VALIST_BY_REF, 4446 (uintptr_t)format, 4447 (uintptr_t)&vargs, 4448 0, 0, 0); 4449 #else 4450 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, 4451 VG_USERREQ__PRINTF_VALIST_BY_REF, 4452 (unsigned long)format, 4453 (unsigned long)&vargs, 4454 0, 0, 0); 4455 #endif 4456 va_end(vargs); 4457 return (int)_qzz_res; 4458 } 4459 4460 #if !defined(_MSC_VER) 4461 static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...) 4462 __attribute__((format(__printf__, 1, 2), __unused__)); 4463 #endif 4464 static int 4465 #if defined(_MSC_VER) 4466 __inline 4467 #endif 4468 VALGRIND_PRINTF_BACKTRACE(const char *format, ...) 4469 { 4470 unsigned long _qzz_res; 4471 va_list vargs; 4472 va_start(vargs, format); 4473 #if defined(_MSC_VER) 4474 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, 4475 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF, 4476 (uintptr_t)format, 4477 (uintptr_t)&vargs, 4478 0, 0, 0); 4479 #else 4480 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, 4481 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF, 4482 (unsigned long)format, 4483 (unsigned long)&vargs, 4484 0, 0, 0); 4485 #endif 4486 va_end(vargs); 4487 return (int)_qzz_res; 4488 } 4489 4490 #endif /* NVALGRIND */ 4491 4492 4493 /* These requests allow control to move from the simulated CPU to the 4494 real CPU, calling an arbitary function. 4495 4496 Note that the current ThreadId is inserted as the first argument. 4497 So this call: 4498 4499 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2) 4500 4501 requires f to have this signature: 4502 4503 Word f(Word tid, Word arg1, Word arg2) 4504 4505 where "Word" is a word-sized type. 4506 4507 Note that these client requests are not entirely reliable. For example, 4508 if you call a function with them that subsequently calls printf(), 4509 there's a high chance Valgrind will crash. Generally, your prospects of 4510 these working are made higher if the called function does not refer to 4511 any global variables, and does not refer to any libc or other functions 4512 (printf et al). Any kind of entanglement with libc or dynamic linking is 4513 likely to have a bad outcome, for tricky reasons which we've grappled 4514 with a lot in the past. 4515 */ 4516 #define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \ 4517 __extension__ \ 4518 ({unsigned long _qyy_res; \ 4519 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ 4520 VG_USERREQ__CLIENT_CALL0, \ 4521 _qyy_fn, \ 4522 0, 0, 0, 0); \ 4523 _qyy_res; \ 4524 }) 4525 4526 #define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \ 4527 __extension__ \ 4528 ({unsigned long _qyy_res; \ 4529 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ 4530 VG_USERREQ__CLIENT_CALL1, \ 4531 _qyy_fn, \ 4532 _qyy_arg1, 0, 0, 0); \ 4533 _qyy_res; \ 4534 }) 4535 4536 #define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \ 4537 __extension__ \ 4538 ({unsigned long _qyy_res; \ 4539 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ 4540 VG_USERREQ__CLIENT_CALL2, \ 4541 _qyy_fn, \ 4542 _qyy_arg1, _qyy_arg2, 0, 0); \ 4543 _qyy_res; \ 4544 }) 4545 4546 #define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \ 4547 __extension__ \ 4548 ({unsigned long _qyy_res; \ 4549 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ 4550 VG_USERREQ__CLIENT_CALL3, \ 4551 _qyy_fn, \ 4552 _qyy_arg1, _qyy_arg2, \ 4553 _qyy_arg3, 0); \ 4554 _qyy_res; \ 4555 }) 4556 4557 4558 /* Counts the number of errors that have been recorded by a tool. Nb: 4559 the tool must record the errors with VG_(maybe_record_error)() or 4560 VG_(unique_error)() for them to be counted. */ 4561 #define VALGRIND_COUNT_ERRORS \ 4562 __extension__ \ 4563 ({unsigned int _qyy_res; \ 4564 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ 4565 VG_USERREQ__COUNT_ERRORS, \ 4566 0, 0, 0, 0, 0); \ 4567 _qyy_res; \ 4568 }) 4569 4570 /* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing 4571 when heap blocks are allocated in order to give accurate results. This 4572 happens automatically for the standard allocator functions such as 4573 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete, 4574 delete[], etc. 4575 4576 But if your program uses a custom allocator, this doesn't automatically 4577 happen, and Valgrind will not do as well. For example, if you allocate 4578 superblocks with mmap() and then allocates chunks of the superblocks, all 4579 Valgrind's observations will be at the mmap() level and it won't know that 4580 the chunks should be considered separate entities. In Memcheck's case, 4581 that means you probably won't get heap block overrun detection (because 4582 there won't be redzones marked as unaddressable) and you definitely won't 4583 get any leak detection. 4584 4585 The following client requests allow a custom allocator to be annotated so 4586 that it can be handled accurately by Valgrind. 4587 4588 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated 4589 by a malloc()-like function. For Memcheck (an illustrative case), this 4590 does two things: 4591 4592 - It records that the block has been allocated. This means any addresses 4593 within the block mentioned in error messages will be 4594 identified as belonging to the block. It also means that if the block 4595 isn't freed it will be detected by the leak checker. 4596 4597 - It marks the block as being addressable and undefined (if 'is_zeroed' is 4598 not set), or addressable and defined (if 'is_zeroed' is set). This 4599 controls how accesses to the block by the program are handled. 4600 4601 'addr' is the start of the usable block (ie. after any 4602 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator 4603 can apply redzones -- these are blocks of padding at the start and end of 4604 each block. Adding redzones is recommended as it makes it much more likely 4605 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is 4606 zeroed (or filled with another predictable value), as is the case for 4607 calloc(). 4608 4609 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a 4610 heap block -- that will be used by the client program -- is allocated. 4611 It's best to put it at the outermost level of the allocator if possible; 4612 for example, if you have a function my_alloc() which calls 4613 internal_alloc(), and the client request is put inside internal_alloc(), 4614 stack traces relating to the heap block will contain entries for both 4615 my_alloc() and internal_alloc(), which is probably not what you want. 4616 4617 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out 4618 custom blocks from within a heap block, B, that has been allocated with 4619 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking 4620 -- the custom blocks will take precedence. 4621 4622 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For 4623 Memcheck, it does two things: 4624 4625 - It records that the block has been deallocated. This assumes that the 4626 block was annotated as having been allocated via 4627 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued. 4628 4629 - It marks the block as being unaddressable. 4630 4631 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a 4632 heap block is deallocated. 4633 4634 In many cases, these two client requests will not be enough to get your 4635 allocator working well with Memcheck. More specifically, if your allocator 4636 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call 4637 will be necessary to mark the memory as addressable just before the zeroing 4638 occurs, otherwise you'll get a lot of invalid write errors. For example, 4639 you'll need to do this if your allocator recycles freed blocks, but it 4640 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK). 4641 Alternatively, if your allocator reuses freed blocks for allocator-internal 4642 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary. 4643 4644 Really, what's happening is a blurring of the lines between the client 4645 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the 4646 memory should be considered unaddressable to the client program, but the 4647 allocator knows more than the rest of the client program and so may be able 4648 to safely access it. Extra client requests are necessary for Valgrind to 4649 understand the distinction between the allocator and the rest of the 4650 program. 4651 4652 Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it 4653 has to be emulated with MALLOCLIKE/FREELIKE and memory copying. 4654 4655 Ignored if addr == 0. 4656 */ 4657 #define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ 4658 {unsigned int _qzz_res; \ 4659 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 4660 VG_USERREQ__MALLOCLIKE_BLOCK, \ 4661 addr, sizeB, rzB, is_zeroed, 0); \ 4662 } 4663 4664 /* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details. 4665 Ignored if addr == 0. 4666 */ 4667 #define VALGRIND_FREELIKE_BLOCK(addr, rzB) \ 4668 {unsigned int _qzz_res; \ 4669 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 4670 VG_USERREQ__FREELIKE_BLOCK, \ 4671 addr, rzB, 0, 0, 0); \ 4672 } 4673 4674 /* Create a memory pool. */ 4675 #define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \ 4676 {unsigned int _qzz_res; \ 4677 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 4678 VG_USERREQ__CREATE_MEMPOOL, \ 4679 pool, rzB, is_zeroed, 0, 0); \ 4680 } 4681 4682 /* Destroy a memory pool. */ 4683 #define VALGRIND_DESTROY_MEMPOOL(pool) \ 4684 {unsigned int _qzz_res; \ 4685 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 4686 VG_USERREQ__DESTROY_MEMPOOL, \ 4687 pool, 0, 0, 0, 0); \ 4688 } 4689 4690 /* Associate a piece of memory with a memory pool. */ 4691 #define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \ 4692 {unsigned int _qzz_res; \ 4693 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 4694 VG_USERREQ__MEMPOOL_ALLOC, \ 4695 pool, addr, size, 0, 0); \ 4696 } 4697 4698 /* Disassociate a piece of memory from a memory pool. */ 4699 #define VALGRIND_MEMPOOL_FREE(pool, addr) \ 4700 {unsigned int _qzz_res; \ 4701 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 4702 VG_USERREQ__MEMPOOL_FREE, \ 4703 pool, addr, 0, 0, 0); \ 4704 } 4705 4706 /* Disassociate any pieces outside a particular range. */ 4707 #define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \ 4708 {unsigned int _qzz_res; \ 4709 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 4710 VG_USERREQ__MEMPOOL_TRIM, \ 4711 pool, addr, size, 0, 0); \ 4712 } 4713 4714 /* Resize and/or move a piece associated with a memory pool. */ 4715 #define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \ 4716 {unsigned int _qzz_res; \ 4717 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 4718 VG_USERREQ__MOVE_MEMPOOL, \ 4719 poolA, poolB, 0, 0, 0); \ 4720 } 4721 4722 /* Resize and/or move a piece associated with a memory pool. */ 4723 #define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \ 4724 {unsigned int _qzz_res; \ 4725 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 4726 VG_USERREQ__MEMPOOL_CHANGE, \ 4727 pool, addrA, addrB, size, 0); \ 4728 } 4729 4730 /* Return 1 if a mempool exists, else 0. */ 4731 #define VALGRIND_MEMPOOL_EXISTS(pool) \ 4732 __extension__ \ 4733 ({unsigned int _qzz_res; \ 4734 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 4735 VG_USERREQ__MEMPOOL_EXISTS, \ 4736 pool, 0, 0, 0, 0); \ 4737 _qzz_res; \ 4738 }) 4739 4740 /* Mark a piece of memory as being a stack. Returns a stack id. */ 4741 #define VALGRIND_STACK_REGISTER(start, end) \ 4742 __extension__ \ 4743 ({unsigned int _qzz_res; \ 4744 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 4745 VG_USERREQ__STACK_REGISTER, \ 4746 start, end, 0, 0, 0); \ 4747 _qzz_res; \ 4748 }) 4749 4750 /* Unmark the piece of memory associated with a stack id as being a 4751 stack. */ 4752 #define VALGRIND_STACK_DEREGISTER(id) \ 4753 {unsigned int _qzz_res; \ 4754 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 4755 VG_USERREQ__STACK_DEREGISTER, \ 4756 id, 0, 0, 0, 0); \ 4757 } 4758 4759 /* Change the start and end address of the stack id. */ 4760 #define VALGRIND_STACK_CHANGE(id, start, end) \ 4761 {unsigned int _qzz_res; \ 4762 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 4763 VG_USERREQ__STACK_CHANGE, \ 4764 id, start, end, 0, 0); \ 4765 } 4766 4767 /* Load PDB debug info for Wine PE image_map. */ 4768 #define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \ 4769 {unsigned int _qzz_res; \ 4770 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 4771 VG_USERREQ__LOAD_PDB_DEBUGINFO, \ 4772 fd, ptr, total_size, delta, 0); \ 4773 } 4774 4775 /* Map a code address to a source file name and line number. buf64 4776 must point to a 64-byte buffer in the caller's address space. The 4777 result will be dumped in there and is guaranteed to be zero 4778 terminated. If no info is found, the first byte is set to zero. */ 4779 #define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \ 4780 {unsigned int _qzz_res; \ 4781 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ 4782 VG_USERREQ__MAP_IP_TO_SRCLOC, \ 4783 addr, buf64, 0, 0, 0); \ 4784 } 4785 4786 4787 #undef PLAT_x86_linux 4788 #undef PLAT_amd64_linux 4789 #undef PLAT_ppc32_linux 4790 #undef PLAT_ppc64_linux 4791 #undef PLAT_arm_linux 4792 #undef PLAT_ppc32_aix5 4793 #undef PLAT_ppc64_aix5 4794 4795 #endif /* __VALGRIND_H */ 4796 4797 #endif 4798