YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

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