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