Coverage Report

Created: 2025-07-23 08:13

/src/pango/subprojects/glib/glib/valgrind.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- c -*-
2
   ----------------------------------------------------------------
3
4
   Notice that the following BSD-style license applies to this one
5
   file (valgrind.h) only.  The rest of Valgrind is licensed under the
6
   terms of the GNU General Public License, version 2, unless
7
   otherwise indicated.  See the COPYING file in the source
8
   distribution for details.
9
10
   ----------------------------------------------------------------
11
12
   This file is part of Valgrind, a dynamic binary instrumentation
13
   framework.
14
15
   Copyright (C) 2000-2017 Julian Seward.  All rights reserved.
16
17
   Redistribution and use in source and binary forms, with or without
18
   modification, are permitted provided that the following conditions
19
   are met:
20
21
   1. Redistributions of source code must retain the above copyright
22
      notice, this list of conditions and the following disclaimer.
23
24
   2. The origin of this software must not be misrepresented; you must 
25
      not claim that you wrote the original software.  If you use this 
26
      software in a product, an acknowledgment in the product 
27
      documentation would be appreciated but is not required.
28
29
   3. Altered source versions must be plainly marked as such, and must
30
      not be misrepresented as being the original software.
31
32
   4. The name of the author may not be used to endorse or promote 
33
      products derived from this software without specific prior written 
34
      permission.
35
36
   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
37
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39
   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
40
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41
   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42
   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44
   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
45
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47
48
   ----------------------------------------------------------------
49
50
   Notice that the above BSD-style license applies to this one file
51
   (valgrind.h) only.  The entire rest of Valgrind is licensed under
52
   the terms of the GNU General Public License, version 2.  See the
53
   COPYING file in the source distribution for details.
54
55
   ---------------------------------------------------------------- 
56
*/
57
58
59
/* This file is for inclusion into client (your!) code.
60
61
   You can use these macros to manipulate and query Valgrind's 
62
   execution inside your own programs.
63
64
   The resulting executables will still run without Valgrind, just a
65
   little bit more slowly than they otherwise would, but otherwise
66
   unchanged.  When not running on valgrind, each client request
67
   consumes very few (eg. 7) instructions, so the resulting performance
68
   loss is negligible unless you plan to execute client requests
69
   millions of times per second.  Nevertheless, if that is still a
70
   problem, you can compile with the NVALGRIND symbol defined (gcc
71
   -DNVALGRIND) so that client requests are not even compiled in.  */
72
73
#ifndef __VALGRIND_H
74
#define __VALGRIND_H
75
76
77
/* ------------------------------------------------------------------ */
78
/* VERSION NUMBER OF VALGRIND                                         */
79
/* ------------------------------------------------------------------ */
80
81
/* Specify Valgrind's version number, so that user code can
82
   conditionally compile based on our version number.  Note that these
83
   were introduced at version 3.6 and so do not exist in version 3.5
84
   or earlier.  The recommended way to use them to check for "version
85
   X.Y or later" is (eg)
86
87
#if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__)   \
88
    && (__VALGRIND_MAJOR__ > 3                                   \
89
        || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6))
90
*/
91
#define __VALGRIND_MAJOR__    3
92
#define __VALGRIND_MINOR__    15
93
94
95
#include <stdarg.h>
96
#include <stdint.h>
97
98
/* Nb: this file might be included in a file compiled with -ansi.  So
99
   we can't use C++ style "//" comments nor the "asm" keyword (instead
100
   use "__asm__"). */
101
102
/* Derive some tags indicating what the target platform is.  Note
103
   that in this file we're using the compiler's CPP symbols for
104
   identifying architectures, which are different to the ones we use
105
   within the rest of Valgrind.  Note, __powerpc__ is active for both
106
   32 and 64-bit PPC, whereas __powerpc64__ is only active for the
107
   latter (on Linux, that is).
108
109
   Misc note: how to find out what's predefined in gcc by default:
110
   gcc -Wp,-dM somefile.c
111
*/
112
#undef PLAT_x86_darwin
113
#undef PLAT_amd64_darwin
114
#undef PLAT_x86_win32
115
#undef PLAT_amd64_win64
116
#undef PLAT_x86_linux
117
#undef PLAT_amd64_linux
118
#undef PLAT_ppc32_linux
119
#undef PLAT_ppc64be_linux
120
#undef PLAT_ppc64le_linux
121
#undef PLAT_arm_linux
122
#undef PLAT_arm64_linux
123
#undef PLAT_s390x_linux
124
#undef PLAT_mips32_linux
125
#undef PLAT_mips64_linux
126
#undef PLAT_x86_solaris
127
#undef PLAT_amd64_solaris
128
129
130
#if defined(__APPLE__) && defined(__i386__)
131
#  define PLAT_x86_darwin 1
132
#elif defined(__APPLE__) && defined(__x86_64__)
133
#  define PLAT_amd64_darwin 1
134
#elif (defined(__MINGW32__) && defined(__i386__)) \
135
      || defined(__CYGWIN32__) \
136
      || (defined(_WIN32) && defined(_M_IX86))
137
#  define PLAT_x86_win32 1
138
#elif (defined(__MINGW32__) && defined(__x86_64__)) \
139
      || (defined(_WIN32) && defined(_M_X64))
140
/* __MINGW32__ and _WIN32 are defined in 64 bit mode as well. */
141
#  define PLAT_amd64_win64 1
142
#elif defined(__linux__) && defined(__i386__)
143
#  define PLAT_x86_linux 1
144
#elif defined(__linux__) && defined(__x86_64__) && !defined(__ILP32__)
145
#  define PLAT_amd64_linux 1
146
#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
147
#  define PLAT_ppc32_linux 1
148
#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF != 2
149
/* Big Endian uses ELF version 1 */
150
#  define PLAT_ppc64be_linux 1
151
#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF == 2
152
/* Little Endian uses ELF version 2 */
153
#  define PLAT_ppc64le_linux 1
154
#elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__)
155
#  define PLAT_arm_linux 1
156
#elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__)
157
#  define PLAT_arm64_linux 1
158
#elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
159
#  define PLAT_s390x_linux 1
160
#elif defined(__linux__) && defined(__mips__) && (__mips==64)
161
#  define PLAT_mips64_linux 1
162
#elif defined(__linux__) && defined(__mips__) && (__mips!=64)
163
#  define PLAT_mips32_linux 1
164
#elif defined(__sun) && defined(__i386__)
165
#  define PLAT_x86_solaris 1
166
#elif defined(__sun) && defined(__x86_64__)
167
#  define PLAT_amd64_solaris 1
168
#else
169
/* If we're not compiling for our target platform, don't generate
170
   any inline asms.  */
171
#  if !defined(NVALGRIND)
172
#    define NVALGRIND 1
173
#  endif
174
#endif
175
176
177
/* ------------------------------------------------------------------ */
178
/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS.  There is nothing */
179
/* in here of use to end-users -- skip to the next section.           */
180
/* ------------------------------------------------------------------ */
181
182
/*
183
 * VALGRIND_DO_CLIENT_REQUEST(): a statement that invokes a Valgrind client
184
 * request. Accepts both pointers and integers as arguments.
185
 *
186
 * VALGRIND_DO_CLIENT_REQUEST_STMT(): a statement that invokes a Valgrind
187
 * client request that does not return a value.
188
189
 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
190
 * client request and whose value equals the client request result.  Accepts
191
 * both pointers and integers as arguments.  Note that such calls are not
192
 * necessarily pure functions -- they may have side effects.
193
 */
194
195
#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default,            \
196
                                   _zzq_request, _zzq_arg1, _zzq_arg2,  \
197
                                   _zzq_arg3, _zzq_arg4, _zzq_arg5)     \
198
  do { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default),   \
199
                        (_zzq_request), (_zzq_arg1), (_zzq_arg2),       \
200
                        (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
201
202
#define VALGRIND_DO_CLIENT_REQUEST_STMT(_zzq_request, _zzq_arg1,        \
203
                           _zzq_arg2,  _zzq_arg3, _zzq_arg4, _zzq_arg5) \
204
252
  do { (void) VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                        \
205
252
                    (_zzq_request), (_zzq_arg1), (_zzq_arg2),           \
206
252
                    (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
207
208
#if defined(NVALGRIND)
209
210
/* Define NVALGRIND to completely remove the Valgrind magic sequence
211
   from the compiled code (analogous to NDEBUG's effects on
212
   assert()) */
213
#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
214
        _zzq_default, _zzq_request,                               \
215
        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
216
      (_zzq_default)
217
218
#else  /* ! NVALGRIND */
219
220
/* The following defines the magic code sequences which the JITter
221
   spots and handles magically.  Don't look too closely at them as
222
   they will rot your brain.
223
224
   The assembly code sequences for all architectures is in this one
225
   file.  This is because this file must be stand-alone, and we don't
226
   want to have multiple files.
227
228
   For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
229
   value gets put in the return slot, so that everything works when
230
   this is executed not under Valgrind.  Args are passed in a memory
231
   block, and so there's no intrinsic limit to the number that could
232
   be passed, but it's currently five.
233
   
234
   The macro args are: 
235
      _zzq_rlval    result lvalue
236
      _zzq_default  default value (result returned when running on real CPU)
237
      _zzq_request  request code
238
      _zzq_arg1..5  request params
239
240
   The other two macros are used to support function wrapping, and are
241
   a lot simpler.  VALGRIND_GET_NR_CONTEXT returns the value of the
242
   guest's NRADDR pseudo-register and whatever other information is
243
   needed to safely run the call original from the wrapper: on
244
   ppc64-linux, the R2 value at the divert point is also needed.  This
245
   information is abstracted into a user-visible type, OrigFn.
246
247
   VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
248
   guest, but guarantees that the branch instruction will not be
249
   redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
250
   branch-and-link-to-r11.  VALGRIND_CALL_NOREDIR is just text, not a
251
   complete inline asm, since it needs to be combined with more magic
252
   inline asm stuff to be useful.
253
*/
254
255
/* ----------------- x86-{linux,darwin,solaris} ---------------- */
256
257
#if defined(PLAT_x86_linux)  ||  defined(PLAT_x86_darwin)  \
258
    ||  (defined(PLAT_x86_win32) && defined(__GNUC__)) \
259
    ||  defined(PLAT_x86_solaris)
260
261
typedef
262
   struct { 
263
      unsigned int nraddr; /* where's the code? */
264
   }
265
   OrigFn;
266
267
#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
268
                     "roll $3,  %%edi ; roll $13, %%edi\n\t"      \
269
                     "roll $29, %%edi ; roll $19, %%edi\n\t"
270
271
#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
272
        _zzq_default, _zzq_request,                               \
273
        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
274
  __extension__                                                   \
275
  ({volatile unsigned int _zzq_args[6];                           \
276
    volatile unsigned int _zzq_result;                            \
277
    _zzq_args[0] = (unsigned int)(_zzq_request);                  \
278
    _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
279
    _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
280
    _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
281
    _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
282
    _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
283
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
284
                     /* %EDX = client_request ( %EAX ) */         \
285
                     "xchgl %%ebx,%%ebx"                          \
286
                     : "=d" (_zzq_result)                         \
287
                     : "a" (&_zzq_args[0]), "0" (_zzq_default)    \
288
                     : "cc", "memory"                             \
289
                    );                                            \
290
    _zzq_result;                                                  \
291
  })
292
293
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
294
  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
295
    volatile unsigned int __addr;                                 \
296
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
297
                     /* %EAX = guest_NRADDR */                    \
298
                     "xchgl %%ecx,%%ecx"                          \
299
                     : "=a" (__addr)                              \
300
                     :                                            \
301
                     : "cc", "memory"                             \
302
                    );                                            \
303
    _zzq_orig->nraddr = __addr;                                   \
304
  }
305
306
#define VALGRIND_CALL_NOREDIR_EAX                                 \
307
                     __SPECIAL_INSTRUCTION_PREAMBLE               \
308
                     /* call-noredir *%EAX */                     \
309
                     "xchgl %%edx,%%edx\n\t"
310
311
#define VALGRIND_VEX_INJECT_IR()                                 \
312
 do {                                                            \
313
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
314
                     "xchgl %%edi,%%edi\n\t"                     \
315
                     : : : "cc", "memory"                        \
316
                    );                                           \
317
 } while (0)
318
319
#endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__)
320
          || PLAT_x86_solaris */
321
322
/* ------------------------- x86-Win32 ------------------------- */
323
324
#if defined(PLAT_x86_win32) && !defined(__GNUC__)
325
326
typedef
327
   struct { 
328
      unsigned int nraddr; /* where's the code? */
329
   }
330
   OrigFn;
331
332
#if defined(_MSC_VER)
333
334
#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
335
                     __asm rol edi, 3  __asm rol edi, 13          \
336
                     __asm rol edi, 29 __asm rol edi, 19
337
338
#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
339
        _zzq_default, _zzq_request,                               \
340
        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
341
    valgrind_do_client_request_expr((uintptr_t)(_zzq_default),    \
342
        (uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1),        \
343
        (uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3),           \
344
        (uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5))
345
346
static __inline uintptr_t
347
valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request,
348
                                uintptr_t _zzq_arg1, uintptr_t _zzq_arg2,
349
                                uintptr_t _zzq_arg3, uintptr_t _zzq_arg4,
350
                                uintptr_t _zzq_arg5)
351
{
352
    volatile uintptr_t _zzq_args[6];
353
    volatile unsigned int _zzq_result;
354
    _zzq_args[0] = (uintptr_t)(_zzq_request);
355
    _zzq_args[1] = (uintptr_t)(_zzq_arg1);
356
    _zzq_args[2] = (uintptr_t)(_zzq_arg2);
357
    _zzq_args[3] = (uintptr_t)(_zzq_arg3);
358
    _zzq_args[4] = (uintptr_t)(_zzq_arg4);
359
    _zzq_args[5] = (uintptr_t)(_zzq_arg5);
360
    __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default
361
            __SPECIAL_INSTRUCTION_PREAMBLE
362
            /* %EDX = client_request ( %EAX ) */
363
            __asm xchg ebx,ebx
364
            __asm mov _zzq_result, edx
365
    }
366
    return _zzq_result;
367
}
368
369
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
370
  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
371
    volatile unsigned int __addr;                                 \
372
    __asm { __SPECIAL_INSTRUCTION_PREAMBLE                        \
373
            /* %EAX = guest_NRADDR */                             \
374
            __asm xchg ecx,ecx                                    \
375
            __asm mov __addr, eax                                 \
376
    }                                                             \
377
    _zzq_orig->nraddr = __addr;                                   \
378
  }
379
380
#define VALGRIND_CALL_NOREDIR_EAX ERROR
381
382
#define VALGRIND_VEX_INJECT_IR()                                 \
383
 do {                                                            \
384
    __asm { __SPECIAL_INSTRUCTION_PREAMBLE                       \
385
            __asm xchg edi,edi                                   \
386
    }                                                            \
387
 } while (0)
388
389
#else
390
#error Unsupported compiler.
391
#endif
392
393
#endif /* PLAT_x86_win32 */
394
395
/* ----------------- amd64-{linux,darwin,solaris} --------------- */
396
397
#if defined(PLAT_amd64_linux)  ||  defined(PLAT_amd64_darwin) \
398
    ||  defined(PLAT_amd64_solaris) \
399
    ||  (defined(PLAT_amd64_win64) && defined(__GNUC__))
400
401
typedef
402
   struct { 
403
      unsigned long int nraddr; /* where's the code? */
404
   }
405
   OrigFn;
406
407
#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
408
                     "rolq $3,  %%rdi ; rolq $13, %%rdi\n\t"      \
409
                     "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
410
411
#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
412
        _zzq_default, _zzq_request,                               \
413
        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
414
322
    __extension__                                                 \
415
322
    ({ volatile uintptr_t _zzq_args[6];                           \
416
322
    volatile unsigned long int _zzq_result;                       \
417
322
    _zzq_args[0] = (uintptr_t)(_zzq_request);                     \
418
322
    _zzq_args[1] = (uintptr_t)(_zzq_arg1);                        \
419
1.00k
    _zzq_args[2] = (uintptr_t)(_zzq_arg2);                        \
420
322
    _zzq_args[3] = (uintptr_t)(_zzq_arg3);                        \
421
322
    _zzq_args[4] = (uintptr_t)(_zzq_arg4);                        \
422
322
    _zzq_args[5] = (uintptr_t)(_zzq_arg5);                        \
423
322
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
424
322
                     /* %RDX = client_request ( %RAX ) */         \
425
322
                     "xchgq %%rbx,%%rbx"                          \
426
322
                     : "=d" (_zzq_result)                         \
427
322
                     : "a" (&_zzq_args[0]), "0" (_zzq_default)    \
428
322
                     : "cc", "memory"                             \
429
322
                    );                                            \
430
322
    _zzq_result;                                                  \
431
322
    })
432
433
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
434
  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
435
    volatile unsigned long int __addr;                            \
436
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
437
                     /* %RAX = guest_NRADDR */                    \
438
                     "xchgq %%rcx,%%rcx"                          \
439
                     : "=a" (__addr)                              \
440
                     :                                            \
441
                     : "cc", "memory"                             \
442
                    );                                            \
443
    _zzq_orig->nraddr = __addr;                                   \
444
  }
445
446
#define VALGRIND_CALL_NOREDIR_RAX                                 \
447
                     __SPECIAL_INSTRUCTION_PREAMBLE               \
448
                     /* call-noredir *%RAX */                     \
449
                     "xchgq %%rdx,%%rdx\n\t"
450
451
#define VALGRIND_VEX_INJECT_IR()                                 \
452
 do {                                                            \
453
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
454
                     "xchgq %%rdi,%%rdi\n\t"                     \
455
                     : : : "cc", "memory"                        \
456
                    );                                           \
457
 } while (0)
458
459
#endif /* PLAT_amd64_linux || PLAT_amd64_darwin || PLAT_amd64_solaris */
460
461
/* ------------------------- amd64-Win64 ------------------------- */
462
463
#if defined(PLAT_amd64_win64) && !defined(__GNUC__)
464
465
#error Unsupported compiler.
466
467
#endif /* PLAT_amd64_win64 */
468
469
/* ------------------------ ppc32-linux ------------------------ */
470
471
#if defined(PLAT_ppc32_linux)
472
473
typedef
474
   struct { 
475
      unsigned int nraddr; /* where's the code? */
476
   }
477
   OrigFn;
478
479
#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
480
                    "rlwinm 0,0,3,0,31  ; rlwinm 0,0,13,0,31\n\t" \
481
                    "rlwinm 0,0,29,0,31 ; rlwinm 0,0,19,0,31\n\t"
482
483
#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
484
        _zzq_default, _zzq_request,                               \
485
        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
486
                                                                  \
487
    __extension__                                                 \
488
  ({         unsigned int  _zzq_args[6];                          \
489
             unsigned int  _zzq_result;                           \
490
             unsigned int* _zzq_ptr;                              \
491
    _zzq_args[0] = (unsigned int)(_zzq_request);                  \
492
    _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
493
    _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
494
    _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
495
    _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
496
    _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
497
    _zzq_ptr = _zzq_args;                                         \
498
    __asm__ volatile("mr 3,%1\n\t" /*default*/                    \
499
                     "mr 4,%2\n\t" /*ptr*/                        \
500
                     __SPECIAL_INSTRUCTION_PREAMBLE               \
501
                     /* %R3 = client_request ( %R4 ) */           \
502
                     "or 1,1,1\n\t"                               \
503
                     "mr %0,3"     /*result*/                     \
504
                     : "=b" (_zzq_result)                         \
505
                     : "b" (_zzq_default), "b" (_zzq_ptr)         \
506
                     : "cc", "memory", "r3", "r4");               \
507
    _zzq_result;                                                  \
508
    })
509
510
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
511
  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
512
    unsigned int __addr;                                          \
513
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
514
                     /* %R3 = guest_NRADDR */                     \
515
                     "or 2,2,2\n\t"                               \
516
                     "mr %0,3"                                    \
517
                     : "=b" (__addr)                              \
518
                     :                                            \
519
                     : "cc", "memory", "r3"                       \
520
                    );                                            \
521
    _zzq_orig->nraddr = __addr;                                   \
522
  }
523
524
#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                   \
525
                     __SPECIAL_INSTRUCTION_PREAMBLE               \
526
                     /* branch-and-link-to-noredir *%R11 */       \
527
                     "or 3,3,3\n\t"
528
529
#define VALGRIND_VEX_INJECT_IR()                                 \
530
 do {                                                            \
531
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
532
                     "or 5,5,5\n\t"                              \
533
                    );                                           \
534
 } while (0)
535
536
#endif /* PLAT_ppc32_linux */
537
538
/* ------------------------ ppc64-linux ------------------------ */
539
540
#if defined(PLAT_ppc64be_linux)
541
542
typedef
543
   struct { 
544
      unsigned long int nraddr; /* where's the code? */
545
      unsigned long int r2;  /* what tocptr do we need? */
546
   }
547
   OrigFn;
548
549
#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
550
                     "rotldi 0,0,3  ; rotldi 0,0,13\n\t"          \
551
                     "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
552
553
#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
554
        _zzq_default, _zzq_request,                               \
555
        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
556
                                                                  \
557
  __extension__                                                   \
558
  ({         unsigned long int  _zzq_args[6];                     \
559
             unsigned long int  _zzq_result;                      \
560
             unsigned long int* _zzq_ptr;                         \
561
    _zzq_args[0] = (unsigned long int)(_zzq_request);             \
562
    _zzq_args[1] = (unsigned long int)(_zzq_arg1);                \
563
    _zzq_args[2] = (unsigned long int)(_zzq_arg2);                \
564
    _zzq_args[3] = (unsigned long int)(_zzq_arg3);                \
565
    _zzq_args[4] = (unsigned long int)(_zzq_arg4);                \
566
    _zzq_args[5] = (unsigned long int)(_zzq_arg5);                \
567
    _zzq_ptr = _zzq_args;                                         \
568
    __asm__ volatile("mr 3,%1\n\t" /*default*/                    \
569
                     "mr 4,%2\n\t" /*ptr*/                        \
570
                     __SPECIAL_INSTRUCTION_PREAMBLE               \
571
                     /* %R3 = client_request ( %R4 ) */           \
572
                     "or 1,1,1\n\t"                               \
573
                     "mr %0,3"     /*result*/                     \
574
                     : "=b" (_zzq_result)                         \
575
                     : "b" (_zzq_default), "b" (_zzq_ptr)         \
576
                     : "cc", "memory", "r3", "r4");               \
577
    _zzq_result;                                                  \
578
  })
579
580
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
581
  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
582
    unsigned long int __addr;                                     \
583
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
584
                     /* %R3 = guest_NRADDR */                     \
585
                     "or 2,2,2\n\t"                               \
586
                     "mr %0,3"                                    \
587
                     : "=b" (__addr)                              \
588
                     :                                            \
589
                     : "cc", "memory", "r3"                       \
590
                    );                                            \
591
    _zzq_orig->nraddr = __addr;                                   \
592
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
593
                     /* %R3 = guest_NRADDR_GPR2 */                \
594
                     "or 4,4,4\n\t"                               \
595
                     "mr %0,3"                                    \
596
                     : "=b" (__addr)                              \
597
                     :                                            \
598
                     : "cc", "memory", "r3"                       \
599
                    );                                            \
600
    _zzq_orig->r2 = __addr;                                       \
601
  }
602
603
#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                   \
604
                     __SPECIAL_INSTRUCTION_PREAMBLE               \
605
                     /* branch-and-link-to-noredir *%R11 */       \
606
                     "or 3,3,3\n\t"
607
608
#define VALGRIND_VEX_INJECT_IR()                                 \
609
 do {                                                            \
610
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
611
                     "or 5,5,5\n\t"                              \
612
                    );                                           \
613
 } while (0)
614
615
#endif /* PLAT_ppc64be_linux */
616
617
#if defined(PLAT_ppc64le_linux)
618
619
typedef
620
   struct {
621
      unsigned long int nraddr; /* where's the code? */
622
      unsigned long int r2;     /* what tocptr do we need? */
623
   }
624
   OrigFn;
625
626
#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
627
                     "rotldi 0,0,3  ; rotldi 0,0,13\n\t"          \
628
                     "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
629
630
#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
631
        _zzq_default, _zzq_request,                               \
632
        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
633
                                                                  \
634
  __extension__                                                   \
635
  ({         unsigned long int  _zzq_args[6];                     \
636
             unsigned long int  _zzq_result;                      \
637
             unsigned long int* _zzq_ptr;                         \
638
    _zzq_args[0] = (unsigned long int)(_zzq_request);             \
639
    _zzq_args[1] = (unsigned long int)(_zzq_arg1);                \
640
    _zzq_args[2] = (unsigned long int)(_zzq_arg2);                \
641
    _zzq_args[3] = (unsigned long int)(_zzq_arg3);                \
642
    _zzq_args[4] = (unsigned long int)(_zzq_arg4);                \
643
    _zzq_args[5] = (unsigned long int)(_zzq_arg5);                \
644
    _zzq_ptr = _zzq_args;                                         \
645
    __asm__ volatile("mr 3,%1\n\t" /*default*/                    \
646
                     "mr 4,%2\n\t" /*ptr*/                        \
647
                     __SPECIAL_INSTRUCTION_PREAMBLE               \
648
                     /* %R3 = client_request ( %R4 ) */           \
649
                     "or 1,1,1\n\t"                               \
650
                     "mr %0,3"     /*result*/                     \
651
                     : "=b" (_zzq_result)                         \
652
                     : "b" (_zzq_default), "b" (_zzq_ptr)         \
653
                     : "cc", "memory", "r3", "r4");               \
654
    _zzq_result;                                                  \
655
  })
656
657
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
658
  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
659
    unsigned long int __addr;                                     \
660
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
661
                     /* %R3 = guest_NRADDR */                     \
662
                     "or 2,2,2\n\t"                               \
663
                     "mr %0,3"                                    \
664
                     : "=b" (__addr)                              \
665
                     :                                            \
666
                     : "cc", "memory", "r3"                       \
667
                    );                                            \
668
    _zzq_orig->nraddr = __addr;                                   \
669
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
670
                     /* %R3 = guest_NRADDR_GPR2 */                \
671
                     "or 4,4,4\n\t"                               \
672
                     "mr %0,3"                                    \
673
                     : "=b" (__addr)                              \
674
                     :                                            \
675
                     : "cc", "memory", "r3"                       \
676
                    );                                            \
677
    _zzq_orig->r2 = __addr;                                       \
678
  }
679
680
#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                   \
681
                     __SPECIAL_INSTRUCTION_PREAMBLE               \
682
                     /* branch-and-link-to-noredir *%R12 */       \
683
                     "or 3,3,3\n\t"
684
685
#define VALGRIND_VEX_INJECT_IR()                                 \
686
 do {                                                            \
687
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
688
                     "or 5,5,5\n\t"                              \
689
                    );                                           \
690
 } while (0)
691
692
#endif /* PLAT_ppc64le_linux */
693
694
/* ------------------------- arm-linux ------------------------- */
695
696
#if defined(PLAT_arm_linux)
697
698
typedef
699
   struct { 
700
      unsigned int nraddr; /* where's the code? */
701
   }
702
   OrigFn;
703
704
#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
705
            "mov r12, r12, ror #3  ; mov r12, r12, ror #13 \n\t"  \
706
            "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
707
708
#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
709
        _zzq_default, _zzq_request,                               \
710
        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
711
                                                                  \
712
  __extension__                                                   \
713
  ({volatile unsigned int  _zzq_args[6];                          \
714
    volatile unsigned int  _zzq_result;                           \
715
    _zzq_args[0] = (unsigned int)(_zzq_request);                  \
716
    _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
717
    _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
718
    _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
719
    _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
720
    _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
721
    __asm__ volatile("mov r3, %1\n\t" /*default*/                 \
722
                     "mov r4, %2\n\t" /*ptr*/                     \
723
                     __SPECIAL_INSTRUCTION_PREAMBLE               \
724
                     /* R3 = client_request ( R4 ) */             \
725
                     "orr r10, r10, r10\n\t"                      \
726
                     "mov %0, r3"     /*result*/                  \
727
                     : "=r" (_zzq_result)                         \
728
                     : "r" (_zzq_default), "r" (&_zzq_args[0])    \
729
                     : "cc","memory", "r3", "r4");                \
730
    _zzq_result;                                                  \
731
  })
732
733
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
734
  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
735
    unsigned int __addr;                                          \
736
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
737
                     /* R3 = guest_NRADDR */                      \
738
                     "orr r11, r11, r11\n\t"                      \
739
                     "mov %0, r3"                                 \
740
                     : "=r" (__addr)                              \
741
                     :                                            \
742
                     : "cc", "memory", "r3"                       \
743
                    );                                            \
744
    _zzq_orig->nraddr = __addr;                                   \
745
  }
746
747
#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                    \
748
                     __SPECIAL_INSTRUCTION_PREAMBLE               \
749
                     /* branch-and-link-to-noredir *%R4 */        \
750
                     "orr r12, r12, r12\n\t"
751
752
#define VALGRIND_VEX_INJECT_IR()                                 \
753
 do {                                                            \
754
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
755
                     "orr r9, r9, r9\n\t"                        \
756
                     : : : "cc", "memory"                        \
757
                    );                                           \
758
 } while (0)
759
760
#endif /* PLAT_arm_linux */
761
762
/* ------------------------ arm64-linux ------------------------- */
763
764
#if defined(PLAT_arm64_linux)
765
766
typedef
767
   struct { 
768
      unsigned long int nraddr; /* where's the code? */
769
   }
770
   OrigFn;
771
772
#define __SPECIAL_INSTRUCTION_PREAMBLE                            \
773
            "ror x12, x12, #3  ;  ror x12, x12, #13 \n\t"         \
774
            "ror x12, x12, #51 ;  ror x12, x12, #61 \n\t"
775
776
#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
777
        _zzq_default, _zzq_request,                               \
778
        _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
779
                                                                  \
780
  __extension__                                                   \
781
  ({volatile unsigned long int  _zzq_args[6];                     \
782
    volatile unsigned long int  _zzq_result;                      \
783
    _zzq_args[0] = (unsigned long int)(_zzq_request);             \
784
    _zzq_args[1] = (unsigned long int)(_zzq_arg1);                \
785
    _zzq_args[2] = (unsigned long int)(_zzq_arg2);                \
786
    _zzq_args[3] = (unsigned long int)(_zzq_arg3);                \
787
    _zzq_args[4] = (unsigned long int)(_zzq_arg4);                \
788
    _zzq_args[5] = (unsigned long int)(_zzq_arg5);                \
789
    __asm__ volatile("mov x3, %1\n\t" /*default*/                 \
790
                     "mov x4, %2\n\t" /*ptr*/                     \
791
                     __SPECIAL_INSTRUCTION_PREAMBLE               \
792
                     /* X3 = client_request ( X4 ) */             \
793
                     "orr x10, x10, x10\n\t"                      \
794
                     "mov %0, x3"     /*result*/                  \
795
                     : "=r" (_zzq_result)                         \
796
                     : "r" ((unsigned long int)(_zzq_default)),   \
797
                       "r" (&_zzq_args[0])                        \
798
                     : "cc","memory", "x3", "x4");                \
799
    _zzq_result;                                                  \
800
  })
801
802
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
803
  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
804
    unsigned long int __addr;                                     \
805
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
806
                     /* X3 = guest_NRADDR */                      \
807
                     "orr x11, x11, x11\n\t"                      \
808
                     "mov %0, x3"                                 \
809
                     : "=r" (__addr)                              \
810
                     :                                            \
811
                     : "cc", "memory", "x3"                       \
812
                    );                                            \
813
    _zzq_orig->nraddr = __addr;                                   \
814
  }
815
816
#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                    \
817
                     __SPECIAL_INSTRUCTION_PREAMBLE               \
818
                     /* branch-and-link-to-noredir X8 */          \
819
                     "orr x12, x12, x12\n\t"
820
821
#define VALGRIND_VEX_INJECT_IR()                                 \
822
 do {                                                            \
823
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
824
                     "orr x9, x9, x9\n\t"                        \
825
                     : : : "cc", "memory"                        \
826
                    );                                           \
827
 } while (0)
828
829
#endif /* PLAT_arm64_linux */
830
831
/* ------------------------ s390x-linux ------------------------ */
832
833
#if defined(PLAT_s390x_linux)
834
835
typedef
836
  struct {
837
     unsigned long int nraddr; /* where's the code? */
838
  }
839
  OrigFn;
840
841
/* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific
842
 * code. This detection is implemented in platform specific toIR.c
843
 * (e.g. VEX/priv/guest_s390_decoder.c).
844
 */
845
#define __SPECIAL_INSTRUCTION_PREAMBLE                           \
846
                     "lr 15,15\n\t"                              \
847
                     "lr 1,1\n\t"                                \
848
                     "lr 2,2\n\t"                                \
849
                     "lr 3,3\n\t"
850
851
#define __CLIENT_REQUEST_CODE "lr 2,2\n\t"
852
#define __GET_NR_CONTEXT_CODE "lr 3,3\n\t"
853
#define __CALL_NO_REDIR_CODE  "lr 4,4\n\t"
854
#define __VEX_INJECT_IR_CODE  "lr 5,5\n\t"
855
856
#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                         \
857
       _zzq_default, _zzq_request,                               \
858
       _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)    \
859
  __extension__                                                  \
860
 ({volatile unsigned long int _zzq_args[6];                      \
861
   volatile unsigned long int _zzq_result;                       \
862
   _zzq_args[0] = (unsigned long int)(_zzq_request);             \
863
   _zzq_args[1] = (unsigned long int)(_zzq_arg1);                \
864
   _zzq_args[2] = (unsigned long int)(_zzq_arg2);                \
865
   _zzq_args[3] = (unsigned long int)(_zzq_arg3);                \
866
   _zzq_args[4] = (unsigned long int)(_zzq_arg4);                \
867
   _zzq_args[5] = (unsigned long int)(_zzq_arg5);                \
868
   __asm__ volatile(/* r2 = args */                              \
869
                    "lgr 2,%1\n\t"                               \
870
                    /* r3 = default */                           \
871
                    "lgr 3,%2\n\t"                               \
872
                    __SPECIAL_INSTRUCTION_PREAMBLE               \
873
                    __CLIENT_REQUEST_CODE                        \
874
                    /* results = r3 */                           \
875
                    "lgr %0, 3\n\t"                              \
876
                    : "=d" (_zzq_result)                         \
877
                    : "a" (&_zzq_args[0]), "0" (_zzq_default)    \
878
                    : "cc", "2", "3", "memory"                   \
879
                   );                                            \
880
   _zzq_result;                                                  \
881
 })
882
883
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                      \
884
 { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
885
   volatile unsigned long int __addr;                            \
886
   __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
887
                    __GET_NR_CONTEXT_CODE                        \
888
                    "lgr %0, 3\n\t"                              \
889
                    : "=a" (__addr)                              \
890
                    :                                            \
891
                    : "cc", "3", "memory"                        \
892
                   );                                            \
893
   _zzq_orig->nraddr = __addr;                                   \
894
 }
895
896
#define VALGRIND_CALL_NOREDIR_R1                                 \
897
                    __SPECIAL_INSTRUCTION_PREAMBLE               \
898
                    __CALL_NO_REDIR_CODE
899
900
#define VALGRIND_VEX_INJECT_IR()                                 \
901
 do {                                                            \
902
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
903
                     __VEX_INJECT_IR_CODE);                      \
904
 } while (0)
905
906
#endif /* PLAT_s390x_linux */
907
908
/* ------------------------- mips32-linux ---------------- */
909
910
#if defined(PLAT_mips32_linux)
911
912
typedef
913
   struct { 
914
      unsigned int nraddr; /* where's the code? */
915
   }
916
   OrigFn;
917
918
/* .word  0x342
919
 * .word  0x742
920
 * .word  0xC2
921
 * .word  0x4C2*/
922
#define __SPECIAL_INSTRUCTION_PREAMBLE          \
923
                     "srl $0, $0, 13\n\t"       \
924
                     "srl $0, $0, 29\n\t"       \
925
                     "srl $0, $0, 3\n\t"        \
926
                     "srl $0, $0, 19\n\t"
927
                    
928
#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                          \
929
       _zzq_default, _zzq_request,                                \
930
       _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)     \
931
  __extension__                                                   \
932
  ({ volatile unsigned int _zzq_args[6];                          \
933
    volatile unsigned int _zzq_result;                            \
934
    _zzq_args[0] = (unsigned int)(_zzq_request);                  \
935
    _zzq_args[1] = (unsigned int)(_zzq_arg1);                     \
936
    _zzq_args[2] = (unsigned int)(_zzq_arg2);                     \
937
    _zzq_args[3] = (unsigned int)(_zzq_arg3);                     \
938
    _zzq_args[4] = (unsigned int)(_zzq_arg4);                     \
939
    _zzq_args[5] = (unsigned int)(_zzq_arg5);                     \
940
        __asm__ volatile("move $11, %1\n\t" /*default*/           \
941
                     "move $12, %2\n\t" /*ptr*/                   \
942
                     __SPECIAL_INSTRUCTION_PREAMBLE               \
943
                     /* T3 = client_request ( T4 ) */             \
944
                     "or $13, $13, $13\n\t"                       \
945
                     "move %0, $11\n\t"     /*result*/            \
946
                     : "=r" (_zzq_result)                         \
947
                     : "r" (_zzq_default), "r" (&_zzq_args[0])    \
948
                     : "$11", "$12", "memory");                   \
949
    _zzq_result;                                                  \
950
  })
951
952
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                       \
953
  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                   \
954
    volatile unsigned int __addr;                                 \
955
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE               \
956
                     /* %t9 = guest_NRADDR */                     \
957
                     "or $14, $14, $14\n\t"                       \
958
                     "move %0, $11"     /*result*/                \
959
                     : "=r" (__addr)                              \
960
                     :                                            \
961
                     : "$11"                                      \
962
                    );                                            \
963
    _zzq_orig->nraddr = __addr;                                   \
964
  }
965
966
#define VALGRIND_CALL_NOREDIR_T9                                 \
967
                     __SPECIAL_INSTRUCTION_PREAMBLE              \
968
                     /* call-noredir *%t9 */                     \
969
                     "or $15, $15, $15\n\t"
970
971
#define VALGRIND_VEX_INJECT_IR()                                 \
972
 do {                                                            \
973
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE              \
974
                     "or $11, $11, $11\n\t"                      \
975
                    );                                           \
976
 } while (0)
977
978
979
#endif /* PLAT_mips32_linux */
980
981
/* ------------------------- mips64-linux ---------------- */
982
983
#if defined(PLAT_mips64_linux)
984
985
typedef
986
   struct {
987
      unsigned long nraddr; /* where's the code? */
988
   }
989
   OrigFn;
990
991
/* dsll $0,$0, 3
992
 * dsll $0,$0, 13
993
 * dsll $0,$0, 29
994
 * dsll $0,$0, 19*/
995
#define __SPECIAL_INSTRUCTION_PREAMBLE                              \
996
                     "dsll $0,$0, 3 ; dsll $0,$0,13\n\t"            \
997
                     "dsll $0,$0,29 ; dsll $0,$0,19\n\t"
998
999
#define VALGRIND_DO_CLIENT_REQUEST_EXPR(                            \
1000
       _zzq_default, _zzq_request,                                  \
1001
       _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5)       \
1002
  __extension__                                                     \
1003
  ({ volatile unsigned long int _zzq_args[6];                       \
1004
    volatile unsigned long int _zzq_result;                         \
1005
    _zzq_args[0] = (unsigned long int)(_zzq_request);               \
1006
    _zzq_args[1] = (unsigned long int)(_zzq_arg1);                  \
1007
    _zzq_args[2] = (unsigned long int)(_zzq_arg2);                  \
1008
    _zzq_args[3] = (unsigned long int)(_zzq_arg3);                  \
1009
    _zzq_args[4] = (unsigned long int)(_zzq_arg4);                  \
1010
    _zzq_args[5] = (unsigned long int)(_zzq_arg5);                  \
1011
        __asm__ volatile("move $11, %1\n\t" /*default*/             \
1012
                         "move $12, %2\n\t" /*ptr*/                 \
1013
                         __SPECIAL_INSTRUCTION_PREAMBLE             \
1014
                         /* $11 = client_request ( $12 ) */         \
1015
                         "or $13, $13, $13\n\t"                     \
1016
                         "move %0, $11\n\t"     /*result*/          \
1017
                         : "=r" (_zzq_result)                       \
1018
                         : "r" (_zzq_default), "r" (&_zzq_args[0])  \
1019
                         : "$11", "$12", "memory");                 \
1020
    _zzq_result;                                                    \
1021
  })
1022
1023
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval)                         \
1024
  { volatile OrigFn* _zzq_orig = &(_zzq_rlval);                     \
1025
    volatile unsigned long int __addr;                              \
1026
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE                 \
1027
                     /* $11 = guest_NRADDR */                       \
1028
                     "or $14, $14, $14\n\t"                         \
1029
                     "move %0, $11"     /*result*/                  \
1030
                     : "=r" (__addr)                                \
1031
                     :                                              \
1032
                     : "$11");                                      \
1033
    _zzq_orig->nraddr = __addr;                                     \
1034
  }
1035
1036
#define VALGRIND_CALL_NOREDIR_T9                                    \
1037
                     __SPECIAL_INSTRUCTION_PREAMBLE                 \
1038
                     /* call-noredir $25 */                         \
1039
                     "or $15, $15, $15\n\t"
1040
1041
#define VALGRIND_VEX_INJECT_IR()                                    \
1042
 do {                                                               \
1043
    __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE                 \
1044
                     "or $11, $11, $11\n\t"                         \
1045
                    );                                              \
1046
 } while (0)
1047
1048
#endif /* PLAT_mips64_linux */
1049
1050
/* Insert assembly code for other platforms here... */
1051
1052
#endif /* NVALGRIND */
1053
1054
1055
/* ------------------------------------------------------------------ */
1056
/* PLATFORM SPECIFICS for FUNCTION WRAPPING.  This is all very        */
1057
/* ugly.  It's the least-worst tradeoff I can think of.               */
1058
/* ------------------------------------------------------------------ */
1059
1060
/* This section defines magic (a.k.a appalling-hack) macros for doing
1061
   guaranteed-no-redirection macros, so as to get from function
1062
   wrappers to the functions they are wrapping.  The whole point is to
1063
   construct standard call sequences, but to do the call itself with a
1064
   special no-redirect call pseudo-instruction that the JIT
1065
   understands and handles specially.  This section is long and
1066
   repetitious, and I can't see a way to make it shorter.
1067
1068
   The naming scheme is as follows:
1069
1070
      CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
1071
1072
   'W' stands for "word" and 'v' for "void".  Hence there are
1073
   different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
1074
   and for each, the possibility of returning a word-typed result, or
1075
   no result.
1076
*/
1077
1078
/* Use these to write the name of your wrapper.  NOTE: duplicates
1079
   VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h.  NOTE also: inserts
1080
   the default behaviour equivalence class tag "0000" into the name.
1081
   See pub_tool_redir.h for details -- normally you don't need to
1082
   think about this, though. */
1083
1084
/* Use an extra level of macroisation so as to ensure the soname/fnname
1085
   args are fully macro-expanded before pasting them together. */
1086
#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
1087
1088
#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname)                    \
1089
   VG_CONCAT4(_vgw00000ZU_,soname,_,fnname)
1090
1091
#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname)                    \
1092
   VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname)
1093
1094
/* Use this macro from within a wrapper function to collect the
1095
   context (address and possibly other info) of the original function.
1096
   Once you have that you can then use it in one of the CALL_FN_
1097
   macros.  The type of the argument _lval is OrigFn. */
1098
#define VALGRIND_GET_ORIG_FN(_lval)  VALGRIND_GET_NR_CONTEXT(_lval)
1099
1100
/* Also provide end-user facilities for function replacement, rather
1101
   than wrapping.  A replacement function differs from a wrapper in
1102
   that it has no way to get hold of the original function being
1103
   called, and hence no way to call onwards to it.  In a replacement
1104
   function, VALGRIND_GET_ORIG_FN always returns zero. */
1105
1106
#define I_REPLACE_SONAME_FNNAME_ZU(soname,fnname)                 \
1107
   VG_CONCAT4(_vgr00000ZU_,soname,_,fnname)
1108
1109
#define I_REPLACE_SONAME_FNNAME_ZZ(soname,fnname)                 \
1110
   VG_CONCAT4(_vgr00000ZZ_,soname,_,fnname)
1111
1112
/* Derivatives of the main macros below, for calling functions
1113
   returning void. */
1114
1115
#define CALL_FN_v_v(fnptr)                                        \
1116
   do { volatile unsigned long _junk;                             \
1117
        CALL_FN_W_v(_junk,fnptr); } while (0)
1118
1119
#define CALL_FN_v_W(fnptr, arg1)                                  \
1120
   do { volatile unsigned long _junk;                             \
1121
        CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
1122
1123
#define CALL_FN_v_WW(fnptr, arg1,arg2)                            \
1124
   do { volatile unsigned long _junk;                             \
1125
        CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
1126
1127
#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3)                      \
1128
   do { volatile unsigned long _junk;                             \
1129
        CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
1130
1131
#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4)                \
1132
   do { volatile unsigned long _junk;                             \
1133
        CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
1134
1135
#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5)             \
1136
   do { volatile unsigned long _junk;                             \
1137
        CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
1138
1139
#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6)        \
1140
   do { volatile unsigned long _junk;                             \
1141
        CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
1142
1143
#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7)   \
1144
   do { volatile unsigned long _junk;                             \
1145
        CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
1146
1147
/* ----------------- x86-{linux,darwin,solaris} ---------------- */
1148
1149
#if defined(PLAT_x86_linux)  ||  defined(PLAT_x86_darwin) \
1150
    ||  defined(PLAT_x86_solaris)
1151
1152
/* These regs are trashed by the hidden call.  No need to mention eax
1153
   as gcc can already see that, plus causes gcc to bomb. */
1154
#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
1155
1156
/* Macros to save and align the stack before making a function
1157
   call and restore it afterwards as gcc may not keep the stack
1158
   pointer aligned if it doesn't realise calls are being made
1159
   to other functions. */
1160
1161
#define VALGRIND_ALIGN_STACK               \
1162
      "movl %%esp,%%edi\n\t"               \
1163
      "andl $0xfffffff0,%%esp\n\t"
1164
#define VALGRIND_RESTORE_STACK             \
1165
      "movl %%edi,%%esp\n\t"
1166
1167
/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
1168
   long) == 4. */
1169
1170
#define CALL_FN_W_v(lval, orig)                                   \
1171
   do {                                                           \
1172
      volatile OrigFn        _orig = (orig);                      \
1173
      volatile unsigned long _argvec[1];                          \
1174
      volatile unsigned long _res;                                \
1175
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1176
      __asm__ volatile(                                           \
1177
         VALGRIND_ALIGN_STACK                                     \
1178
         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1179
         VALGRIND_CALL_NOREDIR_EAX                                \
1180
         VALGRIND_RESTORE_STACK                                   \
1181
         : /*out*/   "=a" (_res)                                  \
1182
         : /*in*/    "a" (&_argvec[0])                            \
1183
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1184
      );                                                          \
1185
      lval = (__typeof__(lval)) _res;                             \
1186
   } while (0)
1187
1188
#define CALL_FN_W_W(lval, orig, arg1)                             \
1189
   do {                                                           \
1190
      volatile OrigFn        _orig = (orig);                      \
1191
      volatile unsigned long _argvec[2];                          \
1192
      volatile unsigned long _res;                                \
1193
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1194
      _argvec[1] = (unsigned long)(arg1);                         \
1195
      __asm__ volatile(                                           \
1196
         VALGRIND_ALIGN_STACK                                     \
1197
         "subl $12, %%esp\n\t"                                    \
1198
         "pushl 4(%%eax)\n\t"                                     \
1199
         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1200
         VALGRIND_CALL_NOREDIR_EAX                                \
1201
         VALGRIND_RESTORE_STACK                                   \
1202
         : /*out*/   "=a" (_res)                                  \
1203
         : /*in*/    "a" (&_argvec[0])                            \
1204
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1205
      );                                                          \
1206
      lval = (__typeof__(lval)) _res;                             \
1207
   } while (0)
1208
1209
#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
1210
   do {                                                           \
1211
      volatile OrigFn        _orig = (orig);                      \
1212
      volatile unsigned long _argvec[3];                          \
1213
      volatile unsigned long _res;                                \
1214
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1215
      _argvec[1] = (unsigned long)(arg1);                         \
1216
      _argvec[2] = (unsigned long)(arg2);                         \
1217
      __asm__ volatile(                                           \
1218
         VALGRIND_ALIGN_STACK                                     \
1219
         "subl $8, %%esp\n\t"                                     \
1220
         "pushl 8(%%eax)\n\t"                                     \
1221
         "pushl 4(%%eax)\n\t"                                     \
1222
         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1223
         VALGRIND_CALL_NOREDIR_EAX                                \
1224
         VALGRIND_RESTORE_STACK                                   \
1225
         : /*out*/   "=a" (_res)                                  \
1226
         : /*in*/    "a" (&_argvec[0])                            \
1227
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1228
      );                                                          \
1229
      lval = (__typeof__(lval)) _res;                             \
1230
   } while (0)
1231
1232
#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
1233
   do {                                                           \
1234
      volatile OrigFn        _orig = (orig);                      \
1235
      volatile unsigned long _argvec[4];                          \
1236
      volatile unsigned long _res;                                \
1237
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1238
      _argvec[1] = (unsigned long)(arg1);                         \
1239
      _argvec[2] = (unsigned long)(arg2);                         \
1240
      _argvec[3] = (unsigned long)(arg3);                         \
1241
      __asm__ volatile(                                           \
1242
         VALGRIND_ALIGN_STACK                                     \
1243
         "subl $4, %%esp\n\t"                                     \
1244
         "pushl 12(%%eax)\n\t"                                    \
1245
         "pushl 8(%%eax)\n\t"                                     \
1246
         "pushl 4(%%eax)\n\t"                                     \
1247
         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1248
         VALGRIND_CALL_NOREDIR_EAX                                \
1249
         VALGRIND_RESTORE_STACK                                   \
1250
         : /*out*/   "=a" (_res)                                  \
1251
         : /*in*/    "a" (&_argvec[0])                            \
1252
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1253
      );                                                          \
1254
      lval = (__typeof__(lval)) _res;                             \
1255
   } while (0)
1256
1257
#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
1258
   do {                                                           \
1259
      volatile OrigFn        _orig = (orig);                      \
1260
      volatile unsigned long _argvec[5];                          \
1261
      volatile unsigned long _res;                                \
1262
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1263
      _argvec[1] = (unsigned long)(arg1);                         \
1264
      _argvec[2] = (unsigned long)(arg2);                         \
1265
      _argvec[3] = (unsigned long)(arg3);                         \
1266
      _argvec[4] = (unsigned long)(arg4);                         \
1267
      __asm__ volatile(                                           \
1268
         VALGRIND_ALIGN_STACK                                     \
1269
         "pushl 16(%%eax)\n\t"                                    \
1270
         "pushl 12(%%eax)\n\t"                                    \
1271
         "pushl 8(%%eax)\n\t"                                     \
1272
         "pushl 4(%%eax)\n\t"                                     \
1273
         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1274
         VALGRIND_CALL_NOREDIR_EAX                                \
1275
         VALGRIND_RESTORE_STACK                                   \
1276
         : /*out*/   "=a" (_res)                                  \
1277
         : /*in*/    "a" (&_argvec[0])                            \
1278
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1279
      );                                                          \
1280
      lval = (__typeof__(lval)) _res;                             \
1281
   } while (0)
1282
1283
#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
1284
   do {                                                           \
1285
      volatile OrigFn        _orig = (orig);                      \
1286
      volatile unsigned long _argvec[6];                          \
1287
      volatile unsigned long _res;                                \
1288
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1289
      _argvec[1] = (unsigned long)(arg1);                         \
1290
      _argvec[2] = (unsigned long)(arg2);                         \
1291
      _argvec[3] = (unsigned long)(arg3);                         \
1292
      _argvec[4] = (unsigned long)(arg4);                         \
1293
      _argvec[5] = (unsigned long)(arg5);                         \
1294
      __asm__ volatile(                                           \
1295
         VALGRIND_ALIGN_STACK                                     \
1296
         "subl $12, %%esp\n\t"                                    \
1297
         "pushl 20(%%eax)\n\t"                                    \
1298
         "pushl 16(%%eax)\n\t"                                    \
1299
         "pushl 12(%%eax)\n\t"                                    \
1300
         "pushl 8(%%eax)\n\t"                                     \
1301
         "pushl 4(%%eax)\n\t"                                     \
1302
         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1303
         VALGRIND_CALL_NOREDIR_EAX                                \
1304
         VALGRIND_RESTORE_STACK                                   \
1305
         : /*out*/   "=a" (_res)                                  \
1306
         : /*in*/    "a" (&_argvec[0])                            \
1307
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1308
      );                                                          \
1309
      lval = (__typeof__(lval)) _res;                             \
1310
   } while (0)
1311
1312
#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
1313
   do {                                                           \
1314
      volatile OrigFn        _orig = (orig);                      \
1315
      volatile unsigned long _argvec[7];                          \
1316
      volatile unsigned long _res;                                \
1317
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1318
      _argvec[1] = (unsigned long)(arg1);                         \
1319
      _argvec[2] = (unsigned long)(arg2);                         \
1320
      _argvec[3] = (unsigned long)(arg3);                         \
1321
      _argvec[4] = (unsigned long)(arg4);                         \
1322
      _argvec[5] = (unsigned long)(arg5);                         \
1323
      _argvec[6] = (unsigned long)(arg6);                         \
1324
      __asm__ volatile(                                           \
1325
         VALGRIND_ALIGN_STACK                                     \
1326
         "subl $8, %%esp\n\t"                                     \
1327
         "pushl 24(%%eax)\n\t"                                    \
1328
         "pushl 20(%%eax)\n\t"                                    \
1329
         "pushl 16(%%eax)\n\t"                                    \
1330
         "pushl 12(%%eax)\n\t"                                    \
1331
         "pushl 8(%%eax)\n\t"                                     \
1332
         "pushl 4(%%eax)\n\t"                                     \
1333
         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1334
         VALGRIND_CALL_NOREDIR_EAX                                \
1335
         VALGRIND_RESTORE_STACK                                   \
1336
         : /*out*/   "=a" (_res)                                  \
1337
         : /*in*/    "a" (&_argvec[0])                            \
1338
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1339
      );                                                          \
1340
      lval = (__typeof__(lval)) _res;                             \
1341
   } while (0)
1342
1343
#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
1344
                                 arg7)                            \
1345
   do {                                                           \
1346
      volatile OrigFn        _orig = (orig);                      \
1347
      volatile unsigned long _argvec[8];                          \
1348
      volatile unsigned long _res;                                \
1349
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1350
      _argvec[1] = (unsigned long)(arg1);                         \
1351
      _argvec[2] = (unsigned long)(arg2);                         \
1352
      _argvec[3] = (unsigned long)(arg3);                         \
1353
      _argvec[4] = (unsigned long)(arg4);                         \
1354
      _argvec[5] = (unsigned long)(arg5);                         \
1355
      _argvec[6] = (unsigned long)(arg6);                         \
1356
      _argvec[7] = (unsigned long)(arg7);                         \
1357
      __asm__ volatile(                                           \
1358
         VALGRIND_ALIGN_STACK                                     \
1359
         "subl $4, %%esp\n\t"                                     \
1360
         "pushl 28(%%eax)\n\t"                                    \
1361
         "pushl 24(%%eax)\n\t"                                    \
1362
         "pushl 20(%%eax)\n\t"                                    \
1363
         "pushl 16(%%eax)\n\t"                                    \
1364
         "pushl 12(%%eax)\n\t"                                    \
1365
         "pushl 8(%%eax)\n\t"                                     \
1366
         "pushl 4(%%eax)\n\t"                                     \
1367
         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1368
         VALGRIND_CALL_NOREDIR_EAX                                \
1369
         VALGRIND_RESTORE_STACK                                   \
1370
         : /*out*/   "=a" (_res)                                  \
1371
         : /*in*/    "a" (&_argvec[0])                            \
1372
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1373
      );                                                          \
1374
      lval = (__typeof__(lval)) _res;                             \
1375
   } while (0)
1376
1377
#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
1378
                                 arg7,arg8)                       \
1379
   do {                                                           \
1380
      volatile OrigFn        _orig = (orig);                      \
1381
      volatile unsigned long _argvec[9];                          \
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
      __asm__ volatile(                                           \
1393
         VALGRIND_ALIGN_STACK                                     \
1394
         "pushl 32(%%eax)\n\t"                                    \
1395
         "pushl 28(%%eax)\n\t"                                    \
1396
         "pushl 24(%%eax)\n\t"                                    \
1397
         "pushl 20(%%eax)\n\t"                                    \
1398
         "pushl 16(%%eax)\n\t"                                    \
1399
         "pushl 12(%%eax)\n\t"                                    \
1400
         "pushl 8(%%eax)\n\t"                                     \
1401
         "pushl 4(%%eax)\n\t"                                     \
1402
         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1403
         VALGRIND_CALL_NOREDIR_EAX                                \
1404
         VALGRIND_RESTORE_STACK                                   \
1405
         : /*out*/   "=a" (_res)                                  \
1406
         : /*in*/    "a" (&_argvec[0])                            \
1407
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1408
      );                                                          \
1409
      lval = (__typeof__(lval)) _res;                             \
1410
   } while (0)
1411
1412
#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
1413
                                 arg7,arg8,arg9)                  \
1414
   do {                                                           \
1415
      volatile OrigFn        _orig = (orig);                      \
1416
      volatile unsigned long _argvec[10];                         \
1417
      volatile unsigned long _res;                                \
1418
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1419
      _argvec[1] = (unsigned long)(arg1);                         \
1420
      _argvec[2] = (unsigned long)(arg2);                         \
1421
      _argvec[3] = (unsigned long)(arg3);                         \
1422
      _argvec[4] = (unsigned long)(arg4);                         \
1423
      _argvec[5] = (unsigned long)(arg5);                         \
1424
      _argvec[6] = (unsigned long)(arg6);                         \
1425
      _argvec[7] = (unsigned long)(arg7);                         \
1426
      _argvec[8] = (unsigned long)(arg8);                         \
1427
      _argvec[9] = (unsigned long)(arg9);                         \
1428
      __asm__ volatile(                                           \
1429
         VALGRIND_ALIGN_STACK                                     \
1430
         "subl $12, %%esp\n\t"                                    \
1431
         "pushl 36(%%eax)\n\t"                                    \
1432
         "pushl 32(%%eax)\n\t"                                    \
1433
         "pushl 28(%%eax)\n\t"                                    \
1434
         "pushl 24(%%eax)\n\t"                                    \
1435
         "pushl 20(%%eax)\n\t"                                    \
1436
         "pushl 16(%%eax)\n\t"                                    \
1437
         "pushl 12(%%eax)\n\t"                                    \
1438
         "pushl 8(%%eax)\n\t"                                     \
1439
         "pushl 4(%%eax)\n\t"                                     \
1440
         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1441
         VALGRIND_CALL_NOREDIR_EAX                                \
1442
         VALGRIND_RESTORE_STACK                                   \
1443
         : /*out*/   "=a" (_res)                                  \
1444
         : /*in*/    "a" (&_argvec[0])                            \
1445
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1446
      );                                                          \
1447
      lval = (__typeof__(lval)) _res;                             \
1448
   } while (0)
1449
1450
#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
1451
                                  arg7,arg8,arg9,arg10)           \
1452
   do {                                                           \
1453
      volatile OrigFn        _orig = (orig);                      \
1454
      volatile unsigned long _argvec[11];                         \
1455
      volatile unsigned long _res;                                \
1456
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1457
      _argvec[1] = (unsigned long)(arg1);                         \
1458
      _argvec[2] = (unsigned long)(arg2);                         \
1459
      _argvec[3] = (unsigned long)(arg3);                         \
1460
      _argvec[4] = (unsigned long)(arg4);                         \
1461
      _argvec[5] = (unsigned long)(arg5);                         \
1462
      _argvec[6] = (unsigned long)(arg6);                         \
1463
      _argvec[7] = (unsigned long)(arg7);                         \
1464
      _argvec[8] = (unsigned long)(arg8);                         \
1465
      _argvec[9] = (unsigned long)(arg9);                         \
1466
      _argvec[10] = (unsigned long)(arg10);                       \
1467
      __asm__ volatile(                                           \
1468
         VALGRIND_ALIGN_STACK                                     \
1469
         "subl $8, %%esp\n\t"                                     \
1470
         "pushl 40(%%eax)\n\t"                                    \
1471
         "pushl 36(%%eax)\n\t"                                    \
1472
         "pushl 32(%%eax)\n\t"                                    \
1473
         "pushl 28(%%eax)\n\t"                                    \
1474
         "pushl 24(%%eax)\n\t"                                    \
1475
         "pushl 20(%%eax)\n\t"                                    \
1476
         "pushl 16(%%eax)\n\t"                                    \
1477
         "pushl 12(%%eax)\n\t"                                    \
1478
         "pushl 8(%%eax)\n\t"                                     \
1479
         "pushl 4(%%eax)\n\t"                                     \
1480
         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1481
         VALGRIND_CALL_NOREDIR_EAX                                \
1482
         VALGRIND_RESTORE_STACK                                   \
1483
         : /*out*/   "=a" (_res)                                  \
1484
         : /*in*/    "a" (&_argvec[0])                            \
1485
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1486
      );                                                          \
1487
      lval = (__typeof__(lval)) _res;                             \
1488
   } while (0)
1489
1490
#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
1491
                                  arg6,arg7,arg8,arg9,arg10,      \
1492
                                  arg11)                          \
1493
   do {                                                           \
1494
      volatile OrigFn        _orig = (orig);                      \
1495
      volatile unsigned long _argvec[12];                         \
1496
      volatile unsigned long _res;                                \
1497
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1498
      _argvec[1] = (unsigned long)(arg1);                         \
1499
      _argvec[2] = (unsigned long)(arg2);                         \
1500
      _argvec[3] = (unsigned long)(arg3);                         \
1501
      _argvec[4] = (unsigned long)(arg4);                         \
1502
      _argvec[5] = (unsigned long)(arg5);                         \
1503
      _argvec[6] = (unsigned long)(arg6);                         \
1504
      _argvec[7] = (unsigned long)(arg7);                         \
1505
      _argvec[8] = (unsigned long)(arg8);                         \
1506
      _argvec[9] = (unsigned long)(arg9);                         \
1507
      _argvec[10] = (unsigned long)(arg10);                       \
1508
      _argvec[11] = (unsigned long)(arg11);                       \
1509
      __asm__ volatile(                                           \
1510
         VALGRIND_ALIGN_STACK                                     \
1511
         "subl $4, %%esp\n\t"                                     \
1512
         "pushl 44(%%eax)\n\t"                                    \
1513
         "pushl 40(%%eax)\n\t"                                    \
1514
         "pushl 36(%%eax)\n\t"                                    \
1515
         "pushl 32(%%eax)\n\t"                                    \
1516
         "pushl 28(%%eax)\n\t"                                    \
1517
         "pushl 24(%%eax)\n\t"                                    \
1518
         "pushl 20(%%eax)\n\t"                                    \
1519
         "pushl 16(%%eax)\n\t"                                    \
1520
         "pushl 12(%%eax)\n\t"                                    \
1521
         "pushl 8(%%eax)\n\t"                                     \
1522
         "pushl 4(%%eax)\n\t"                                     \
1523
         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1524
         VALGRIND_CALL_NOREDIR_EAX                                \
1525
         VALGRIND_RESTORE_STACK                                   \
1526
         : /*out*/   "=a" (_res)                                  \
1527
         : /*in*/    "a" (&_argvec[0])                            \
1528
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1529
      );                                                          \
1530
      lval = (__typeof__(lval)) _res;                             \
1531
   } while (0)
1532
1533
#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
1534
                                  arg6,arg7,arg8,arg9,arg10,      \
1535
                                  arg11,arg12)                    \
1536
   do {                                                           \
1537
      volatile OrigFn        _orig = (orig);                      \
1538
      volatile unsigned long _argvec[13];                         \
1539
      volatile unsigned long _res;                                \
1540
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
1541
      _argvec[1] = (unsigned long)(arg1);                         \
1542
      _argvec[2] = (unsigned long)(arg2);                         \
1543
      _argvec[3] = (unsigned long)(arg3);                         \
1544
      _argvec[4] = (unsigned long)(arg4);                         \
1545
      _argvec[5] = (unsigned long)(arg5);                         \
1546
      _argvec[6] = (unsigned long)(arg6);                         \
1547
      _argvec[7] = (unsigned long)(arg7);                         \
1548
      _argvec[8] = (unsigned long)(arg8);                         \
1549
      _argvec[9] = (unsigned long)(arg9);                         \
1550
      _argvec[10] = (unsigned long)(arg10);                       \
1551
      _argvec[11] = (unsigned long)(arg11);                       \
1552
      _argvec[12] = (unsigned long)(arg12);                       \
1553
      __asm__ volatile(                                           \
1554
         VALGRIND_ALIGN_STACK                                     \
1555
         "pushl 48(%%eax)\n\t"                                    \
1556
         "pushl 44(%%eax)\n\t"                                    \
1557
         "pushl 40(%%eax)\n\t"                                    \
1558
         "pushl 36(%%eax)\n\t"                                    \
1559
         "pushl 32(%%eax)\n\t"                                    \
1560
         "pushl 28(%%eax)\n\t"                                    \
1561
         "pushl 24(%%eax)\n\t"                                    \
1562
         "pushl 20(%%eax)\n\t"                                    \
1563
         "pushl 16(%%eax)\n\t"                                    \
1564
         "pushl 12(%%eax)\n\t"                                    \
1565
         "pushl 8(%%eax)\n\t"                                     \
1566
         "pushl 4(%%eax)\n\t"                                     \
1567
         "movl (%%eax), %%eax\n\t"  /* target->%eax */            \
1568
         VALGRIND_CALL_NOREDIR_EAX                                \
1569
         VALGRIND_RESTORE_STACK                                   \
1570
         : /*out*/   "=a" (_res)                                  \
1571
         : /*in*/    "a" (&_argvec[0])                            \
1572
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi"   \
1573
      );                                                          \
1574
      lval = (__typeof__(lval)) _res;                             \
1575
   } while (0)
1576
1577
#endif /* PLAT_x86_linux || PLAT_x86_darwin || PLAT_x86_solaris */
1578
1579
/* ---------------- amd64-{linux,darwin,solaris} --------------- */
1580
1581
#if defined(PLAT_amd64_linux)  ||  defined(PLAT_amd64_darwin) \
1582
    ||  defined(PLAT_amd64_solaris)
1583
1584
/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
1585
1586
/* These regs are trashed by the hidden call. */
1587
#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi",       \
1588
                            "rdi", "r8", "r9", "r10", "r11"
1589
1590
/* This is all pretty complex.  It's so as to make stack unwinding
1591
   work reliably.  See bug 243270.  The basic problem is the sub and
1592
   add of 128 of %rsp in all of the following macros.  If gcc believes
1593
   the CFA is in %rsp, then unwinding may fail, because what's at the
1594
   CFA is not what gcc "expected" when it constructs the CFIs for the
1595
   places where the macros are instantiated.
1596
1597
   But we can't just add a CFI annotation to increase the CFA offset
1598
   by 128, to match the sub of 128 from %rsp, because we don't know
1599
   whether gcc has chosen %rsp as the CFA at that point, or whether it
1600
   has chosen some other register (eg, %rbp).  In the latter case,
1601
   adding a CFI annotation to change the CFA offset is simply wrong.
1602
1603
   So the solution is to get hold of the CFA using
1604
   __builtin_dwarf_cfa(), put it in a known register, and add a
1605
   CFI annotation to say what the register is.  We choose %rbp for
1606
   this (perhaps perversely), because:
1607
1608
   (1) %rbp is already subject to unwinding.  If a new register was
1609
       chosen then the unwinder would have to unwind it in all stack
1610
       traces, which is expensive, and
1611
1612
   (2) %rbp is already subject to precise exception updates in the
1613
       JIT.  If a new register was chosen, we'd have to have precise
1614
       exceptions for it too, which reduces performance of the
1615
       generated code.
1616
1617
   However .. one extra complication.  We can't just whack the result
1618
   of __builtin_dwarf_cfa() into %rbp and then add %rbp to the
1619
   list of trashed registers at the end of the inline assembly
1620
   fragments; gcc won't allow %rbp to appear in that list.  Hence
1621
   instead we need to stash %rbp in %r15 for the duration of the asm,
1622
   and say that %r15 is trashed instead.  gcc seems happy to go with
1623
   that.
1624
1625
   Oh .. and this all needs to be conditionalised so that it is
1626
   unchanged from before this commit, when compiled with older gccs
1627
   that don't support __builtin_dwarf_cfa.  Furthermore, since
1628
   this header file is freestanding, it has to be independent of
1629
   config.h, and so the following conditionalisation cannot depend on
1630
   configure time checks.
1631
1632
   Although it's not clear from
1633
   'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)',
1634
   this expression excludes Darwin.
1635
   .cfi directives in Darwin assembly appear to be completely
1636
   different and I haven't investigated how they work.
1637
1638
   For even more entertainment value, note we have to use the
1639
   completely undocumented __builtin_dwarf_cfa(), which appears to
1640
   really compute the CFA, whereas __builtin_frame_address(0) claims
1641
   to but actually doesn't.  See
1642
   https://bugs.kde.org/show_bug.cgi?id=243270#c47
1643
*/
1644
#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
1645
#  define __FRAME_POINTER                                         \
1646
      ,"r"(__builtin_dwarf_cfa())
1647
#  define VALGRIND_CFI_PROLOGUE                                   \
1648
      "movq %%rbp, %%r15\n\t"                                     \
1649
      "movq %2, %%rbp\n\t"                                        \
1650
      ".cfi_remember_state\n\t"                                   \
1651
      ".cfi_def_cfa rbp, 0\n\t"
1652
#  define VALGRIND_CFI_EPILOGUE                                   \
1653
      "movq %%r15, %%rbp\n\t"                                     \
1654
      ".cfi_restore_state\n\t"
1655
#else
1656
#  define __FRAME_POINTER
1657
#  define VALGRIND_CFI_PROLOGUE
1658
#  define VALGRIND_CFI_EPILOGUE
1659
#endif
1660
1661
/* Macros to save and align the stack before making a function
1662
   call and restore it afterwards as gcc may not keep the stack
1663
   pointer aligned if it doesn't realise calls are being made
1664
   to other functions. */
1665
1666
#define VALGRIND_ALIGN_STACK               \
1667
      "movq %%rsp,%%r14\n\t"               \
1668
      "andq $0xfffffffffffffff0,%%rsp\n\t"
1669
#define VALGRIND_RESTORE_STACK             \
1670
      "movq %%r14,%%rsp\n\t"
1671
1672
/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
1673
   long) == 8. */
1674
1675
/* NB 9 Sept 07.  There is a nasty kludge here in all these CALL_FN_
1676
   macros.  In order not to trash the stack redzone, we need to drop
1677
   %rsp by 128 before the hidden call, and restore afterwards.  The
1678
   nastiness is that it is only by luck that the stack still appears
1679
   to be unwindable during the hidden call - since then the behaviour
1680
   of any routine using this macro does not match what the CFI data
1681
   says.  Sigh.
1682
1683
   Why is this important?  Imagine that a wrapper has a stack
1684
   allocated local, and passes to the hidden call, a pointer to it.
1685
   Because gcc does not know about the hidden call, it may allocate
1686
   that local in the redzone.  Unfortunately the hidden call may then
1687
   trash it before it comes to use it.  So we must step clear of the
1688
   redzone, for the duration of the hidden call, to make it safe.
1689
1690
   Probably the same problem afflicts the other redzone-style ABIs too
1691
   (ppc64-linux); but for those, the stack is
1692
   self describing (none of this CFI nonsense) so at least messing
1693
   with the stack pointer doesn't give a danger of non-unwindable
1694
   stack. */
1695
1696
#define CALL_FN_W_v(lval, orig)                                        \
1697
   do {                                                                \
1698
      volatile OrigFn        _orig = (orig);                           \
1699
      volatile unsigned long _argvec[1];                               \
1700
      volatile unsigned long _res;                                     \
1701
      _argvec[0] = (unsigned long)_orig.nraddr;                        \
1702
      __asm__ volatile(                                                \
1703
         VALGRIND_CFI_PROLOGUE                                         \
1704
         VALGRIND_ALIGN_STACK                                          \
1705
         "subq $128,%%rsp\n\t"                                         \
1706
         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1707
         VALGRIND_CALL_NOREDIR_RAX                                     \
1708
         VALGRIND_RESTORE_STACK                                        \
1709
         VALGRIND_CFI_EPILOGUE                                         \
1710
         : /*out*/   "=a" (_res)                                       \
1711
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1712
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1713
      );                                                               \
1714
      lval = (__typeof__(lval)) _res;                                  \
1715
   } while (0)
1716
1717
#define CALL_FN_W_W(lval, orig, arg1)                                  \
1718
   do {                                                                \
1719
      volatile OrigFn        _orig = (orig);                           \
1720
      volatile unsigned long _argvec[2];                               \
1721
      volatile unsigned long _res;                                     \
1722
      _argvec[0] = (unsigned long)_orig.nraddr;                        \
1723
      _argvec[1] = (unsigned long)(arg1);                              \
1724
      __asm__ volatile(                                                \
1725
         VALGRIND_CFI_PROLOGUE                                         \
1726
         VALGRIND_ALIGN_STACK                                          \
1727
         "subq $128,%%rsp\n\t"                                         \
1728
         "movq 8(%%rax), %%rdi\n\t"                                    \
1729
         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1730
         VALGRIND_CALL_NOREDIR_RAX                                     \
1731
         VALGRIND_RESTORE_STACK                                        \
1732
         VALGRIND_CFI_EPILOGUE                                         \
1733
         : /*out*/   "=a" (_res)                                       \
1734
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1735
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1736
      );                                                               \
1737
      lval = (__typeof__(lval)) _res;                                  \
1738
   } while (0)
1739
1740
#define CALL_FN_W_WW(lval, orig, arg1,arg2)                            \
1741
   do {                                                                \
1742
      volatile OrigFn        _orig = (orig);                           \
1743
      volatile unsigned long _argvec[3];                               \
1744
      volatile unsigned long _res;                                     \
1745
      _argvec[0] = (unsigned long)_orig.nraddr;                        \
1746
      _argvec[1] = (unsigned long)(arg1);                              \
1747
      _argvec[2] = (unsigned long)(arg2);                              \
1748
      __asm__ volatile(                                                \
1749
         VALGRIND_CFI_PROLOGUE                                         \
1750
         VALGRIND_ALIGN_STACK                                          \
1751
         "subq $128,%%rsp\n\t"                                         \
1752
         "movq 16(%%rax), %%rsi\n\t"                                   \
1753
         "movq 8(%%rax), %%rdi\n\t"                                    \
1754
         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1755
         VALGRIND_CALL_NOREDIR_RAX                                     \
1756
         VALGRIND_RESTORE_STACK                                        \
1757
         VALGRIND_CFI_EPILOGUE                                         \
1758
         : /*out*/   "=a" (_res)                                       \
1759
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1760
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1761
      );                                                               \
1762
      lval = (__typeof__(lval)) _res;                                  \
1763
   } while (0)
1764
1765
#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                      \
1766
   do {                                                                \
1767
      volatile OrigFn        _orig = (orig);                           \
1768
      volatile unsigned long _argvec[4];                               \
1769
      volatile unsigned long _res;                                     \
1770
      _argvec[0] = (unsigned long)_orig.nraddr;                        \
1771
      _argvec[1] = (unsigned long)(arg1);                              \
1772
      _argvec[2] = (unsigned long)(arg2);                              \
1773
      _argvec[3] = (unsigned long)(arg3);                              \
1774
      __asm__ volatile(                                                \
1775
         VALGRIND_CFI_PROLOGUE                                         \
1776
         VALGRIND_ALIGN_STACK                                          \
1777
         "subq $128,%%rsp\n\t"                                         \
1778
         "movq 24(%%rax), %%rdx\n\t"                                   \
1779
         "movq 16(%%rax), %%rsi\n\t"                                   \
1780
         "movq 8(%%rax), %%rdi\n\t"                                    \
1781
         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1782
         VALGRIND_CALL_NOREDIR_RAX                                     \
1783
         VALGRIND_RESTORE_STACK                                        \
1784
         VALGRIND_CFI_EPILOGUE                                         \
1785
         : /*out*/   "=a" (_res)                                       \
1786
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1787
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1788
      );                                                               \
1789
      lval = (__typeof__(lval)) _res;                                  \
1790
   } while (0)
1791
1792
#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)                \
1793
   do {                                                                \
1794
      volatile OrigFn        _orig = (orig);                           \
1795
      volatile unsigned long _argvec[5];                               \
1796
      volatile unsigned long _res;                                     \
1797
      _argvec[0] = (unsigned long)_orig.nraddr;                        \
1798
      _argvec[1] = (unsigned long)(arg1);                              \
1799
      _argvec[2] = (unsigned long)(arg2);                              \
1800
      _argvec[3] = (unsigned long)(arg3);                              \
1801
      _argvec[4] = (unsigned long)(arg4);                              \
1802
      __asm__ volatile(                                                \
1803
         VALGRIND_CFI_PROLOGUE                                         \
1804
         VALGRIND_ALIGN_STACK                                          \
1805
         "subq $128,%%rsp\n\t"                                         \
1806
         "movq 32(%%rax), %%rcx\n\t"                                   \
1807
         "movq 24(%%rax), %%rdx\n\t"                                   \
1808
         "movq 16(%%rax), %%rsi\n\t"                                   \
1809
         "movq 8(%%rax), %%rdi\n\t"                                    \
1810
         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1811
         VALGRIND_CALL_NOREDIR_RAX                                     \
1812
         VALGRIND_RESTORE_STACK                                        \
1813
         VALGRIND_CFI_EPILOGUE                                         \
1814
         : /*out*/   "=a" (_res)                                       \
1815
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1816
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1817
      );                                                               \
1818
      lval = (__typeof__(lval)) _res;                                  \
1819
   } while (0)
1820
1821
#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)             \
1822
   do {                                                                \
1823
      volatile OrigFn        _orig = (orig);                           \
1824
      volatile unsigned long _argvec[6];                               \
1825
      volatile unsigned long _res;                                     \
1826
      _argvec[0] = (unsigned long)_orig.nraddr;                        \
1827
      _argvec[1] = (unsigned long)(arg1);                              \
1828
      _argvec[2] = (unsigned long)(arg2);                              \
1829
      _argvec[3] = (unsigned long)(arg3);                              \
1830
      _argvec[4] = (unsigned long)(arg4);                              \
1831
      _argvec[5] = (unsigned long)(arg5);                              \
1832
      __asm__ volatile(                                                \
1833
         VALGRIND_CFI_PROLOGUE                                         \
1834
         VALGRIND_ALIGN_STACK                                          \
1835
         "subq $128,%%rsp\n\t"                                         \
1836
         "movq 40(%%rax), %%r8\n\t"                                    \
1837
         "movq 32(%%rax), %%rcx\n\t"                                   \
1838
         "movq 24(%%rax), %%rdx\n\t"                                   \
1839
         "movq 16(%%rax), %%rsi\n\t"                                   \
1840
         "movq 8(%%rax), %%rdi\n\t"                                    \
1841
         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1842
         VALGRIND_CALL_NOREDIR_RAX                                     \
1843
         VALGRIND_RESTORE_STACK                                        \
1844
         VALGRIND_CFI_EPILOGUE                                         \
1845
         : /*out*/   "=a" (_res)                                       \
1846
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1847
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1848
      );                                                               \
1849
      lval = (__typeof__(lval)) _res;                                  \
1850
   } while (0)
1851
1852
#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)        \
1853
   do {                                                                \
1854
      volatile OrigFn        _orig = (orig);                           \
1855
      volatile unsigned long _argvec[7];                               \
1856
      volatile unsigned long _res;                                     \
1857
      _argvec[0] = (unsigned long)_orig.nraddr;                        \
1858
      _argvec[1] = (unsigned long)(arg1);                              \
1859
      _argvec[2] = (unsigned long)(arg2);                              \
1860
      _argvec[3] = (unsigned long)(arg3);                              \
1861
      _argvec[4] = (unsigned long)(arg4);                              \
1862
      _argvec[5] = (unsigned long)(arg5);                              \
1863
      _argvec[6] = (unsigned long)(arg6);                              \
1864
      __asm__ volatile(                                                \
1865
         VALGRIND_CFI_PROLOGUE                                         \
1866
         VALGRIND_ALIGN_STACK                                          \
1867
         "subq $128,%%rsp\n\t"                                         \
1868
         "movq 48(%%rax), %%r9\n\t"                                    \
1869
         "movq 40(%%rax), %%r8\n\t"                                    \
1870
         "movq 32(%%rax), %%rcx\n\t"                                   \
1871
         "movq 24(%%rax), %%rdx\n\t"                                   \
1872
         "movq 16(%%rax), %%rsi\n\t"                                   \
1873
         "movq 8(%%rax), %%rdi\n\t"                                    \
1874
         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1875
         VALGRIND_CALL_NOREDIR_RAX                                     \
1876
         VALGRIND_RESTORE_STACK                                        \
1877
         VALGRIND_CFI_EPILOGUE                                         \
1878
         : /*out*/   "=a" (_res)                                       \
1879
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1880
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1881
      );                                                               \
1882
      lval = (__typeof__(lval)) _res;                                  \
1883
   } while (0)
1884
1885
#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,        \
1886
                                 arg7)                                 \
1887
   do {                                                                \
1888
      volatile OrigFn        _orig = (orig);                           \
1889
      volatile unsigned long _argvec[8];                               \
1890
      volatile unsigned long _res;                                     \
1891
      _argvec[0] = (unsigned long)_orig.nraddr;                        \
1892
      _argvec[1] = (unsigned long)(arg1);                              \
1893
      _argvec[2] = (unsigned long)(arg2);                              \
1894
      _argvec[3] = (unsigned long)(arg3);                              \
1895
      _argvec[4] = (unsigned long)(arg4);                              \
1896
      _argvec[5] = (unsigned long)(arg5);                              \
1897
      _argvec[6] = (unsigned long)(arg6);                              \
1898
      _argvec[7] = (unsigned long)(arg7);                              \
1899
      __asm__ volatile(                                                \
1900
         VALGRIND_CFI_PROLOGUE                                         \
1901
         VALGRIND_ALIGN_STACK                                          \
1902
         "subq $136,%%rsp\n\t"                                         \
1903
         "pushq 56(%%rax)\n\t"                                         \
1904
         "movq 48(%%rax), %%r9\n\t"                                    \
1905
         "movq 40(%%rax), %%r8\n\t"                                    \
1906
         "movq 32(%%rax), %%rcx\n\t"                                   \
1907
         "movq 24(%%rax), %%rdx\n\t"                                   \
1908
         "movq 16(%%rax), %%rsi\n\t"                                   \
1909
         "movq 8(%%rax), %%rdi\n\t"                                    \
1910
         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1911
         VALGRIND_CALL_NOREDIR_RAX                                     \
1912
         VALGRIND_RESTORE_STACK                                        \
1913
         VALGRIND_CFI_EPILOGUE                                         \
1914
         : /*out*/   "=a" (_res)                                       \
1915
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1916
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1917
      );                                                               \
1918
      lval = (__typeof__(lval)) _res;                                  \
1919
   } while (0)
1920
1921
#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,        \
1922
                                 arg7,arg8)                            \
1923
   do {                                                                \
1924
      volatile OrigFn        _orig = (orig);                           \
1925
      volatile unsigned long _argvec[9];                               \
1926
      volatile unsigned long _res;                                     \
1927
      _argvec[0] = (unsigned long)_orig.nraddr;                        \
1928
      _argvec[1] = (unsigned long)(arg1);                              \
1929
      _argvec[2] = (unsigned long)(arg2);                              \
1930
      _argvec[3] = (unsigned long)(arg3);                              \
1931
      _argvec[4] = (unsigned long)(arg4);                              \
1932
      _argvec[5] = (unsigned long)(arg5);                              \
1933
      _argvec[6] = (unsigned long)(arg6);                              \
1934
      _argvec[7] = (unsigned long)(arg7);                              \
1935
      _argvec[8] = (unsigned long)(arg8);                              \
1936
      __asm__ volatile(                                                \
1937
         VALGRIND_CFI_PROLOGUE                                         \
1938
         VALGRIND_ALIGN_STACK                                          \
1939
         "subq $128,%%rsp\n\t"                                         \
1940
         "pushq 64(%%rax)\n\t"                                         \
1941
         "pushq 56(%%rax)\n\t"                                         \
1942
         "movq 48(%%rax), %%r9\n\t"                                    \
1943
         "movq 40(%%rax), %%r8\n\t"                                    \
1944
         "movq 32(%%rax), %%rcx\n\t"                                   \
1945
         "movq 24(%%rax), %%rdx\n\t"                                   \
1946
         "movq 16(%%rax), %%rsi\n\t"                                   \
1947
         "movq 8(%%rax), %%rdi\n\t"                                    \
1948
         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1949
         VALGRIND_CALL_NOREDIR_RAX                                     \
1950
         VALGRIND_RESTORE_STACK                                        \
1951
         VALGRIND_CFI_EPILOGUE                                         \
1952
         : /*out*/   "=a" (_res)                                       \
1953
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1954
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1955
      );                                                               \
1956
      lval = (__typeof__(lval)) _res;                                  \
1957
   } while (0)
1958
1959
#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,        \
1960
                                 arg7,arg8,arg9)                       \
1961
   do {                                                                \
1962
      volatile OrigFn        _orig = (orig);                           \
1963
      volatile unsigned long _argvec[10];                              \
1964
      volatile unsigned long _res;                                     \
1965
      _argvec[0] = (unsigned long)_orig.nraddr;                        \
1966
      _argvec[1] = (unsigned long)(arg1);                              \
1967
      _argvec[2] = (unsigned long)(arg2);                              \
1968
      _argvec[3] = (unsigned long)(arg3);                              \
1969
      _argvec[4] = (unsigned long)(arg4);                              \
1970
      _argvec[5] = (unsigned long)(arg5);                              \
1971
      _argvec[6] = (unsigned long)(arg6);                              \
1972
      _argvec[7] = (unsigned long)(arg7);                              \
1973
      _argvec[8] = (unsigned long)(arg8);                              \
1974
      _argvec[9] = (unsigned long)(arg9);                              \
1975
      __asm__ volatile(                                                \
1976
         VALGRIND_CFI_PROLOGUE                                         \
1977
         VALGRIND_ALIGN_STACK                                          \
1978
         "subq $136,%%rsp\n\t"                                         \
1979
         "pushq 72(%%rax)\n\t"                                         \
1980
         "pushq 64(%%rax)\n\t"                                         \
1981
         "pushq 56(%%rax)\n\t"                                         \
1982
         "movq 48(%%rax), %%r9\n\t"                                    \
1983
         "movq 40(%%rax), %%r8\n\t"                                    \
1984
         "movq 32(%%rax), %%rcx\n\t"                                   \
1985
         "movq 24(%%rax), %%rdx\n\t"                                   \
1986
         "movq 16(%%rax), %%rsi\n\t"                                   \
1987
         "movq 8(%%rax), %%rdi\n\t"                                    \
1988
         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
1989
         VALGRIND_CALL_NOREDIR_RAX                                     \
1990
         VALGRIND_RESTORE_STACK                                        \
1991
         VALGRIND_CFI_EPILOGUE                                         \
1992
         : /*out*/   "=a" (_res)                                       \
1993
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
1994
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
1995
      );                                                               \
1996
      lval = (__typeof__(lval)) _res;                                  \
1997
   } while (0)
1998
1999
#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,       \
2000
                                  arg7,arg8,arg9,arg10)                \
2001
   do {                                                                \
2002
      volatile OrigFn        _orig = (orig);                           \
2003
      volatile unsigned long _argvec[11];                              \
2004
      volatile unsigned long _res;                                     \
2005
      _argvec[0] = (unsigned long)_orig.nraddr;                        \
2006
      _argvec[1] = (unsigned long)(arg1);                              \
2007
      _argvec[2] = (unsigned long)(arg2);                              \
2008
      _argvec[3] = (unsigned long)(arg3);                              \
2009
      _argvec[4] = (unsigned long)(arg4);                              \
2010
      _argvec[5] = (unsigned long)(arg5);                              \
2011
      _argvec[6] = (unsigned long)(arg6);                              \
2012
      _argvec[7] = (unsigned long)(arg7);                              \
2013
      _argvec[8] = (unsigned long)(arg8);                              \
2014
      _argvec[9] = (unsigned long)(arg9);                              \
2015
      _argvec[10] = (unsigned long)(arg10);                            \
2016
      __asm__ volatile(                                                \
2017
         VALGRIND_CFI_PROLOGUE                                         \
2018
         VALGRIND_ALIGN_STACK                                          \
2019
         "subq $128,%%rsp\n\t"                                         \
2020
         "pushq 80(%%rax)\n\t"                                         \
2021
         "pushq 72(%%rax)\n\t"                                         \
2022
         "pushq 64(%%rax)\n\t"                                         \
2023
         "pushq 56(%%rax)\n\t"                                         \
2024
         "movq 48(%%rax), %%r9\n\t"                                    \
2025
         "movq 40(%%rax), %%r8\n\t"                                    \
2026
         "movq 32(%%rax), %%rcx\n\t"                                   \
2027
         "movq 24(%%rax), %%rdx\n\t"                                   \
2028
         "movq 16(%%rax), %%rsi\n\t"                                   \
2029
         "movq 8(%%rax), %%rdi\n\t"                                    \
2030
         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
2031
         VALGRIND_CALL_NOREDIR_RAX                                     \
2032
         VALGRIND_RESTORE_STACK                                        \
2033
         VALGRIND_CFI_EPILOGUE                                         \
2034
         : /*out*/   "=a" (_res)                                       \
2035
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
2036
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2037
      );                                                               \
2038
      lval = (__typeof__(lval)) _res;                                  \
2039
   } while (0)
2040
2041
#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,       \
2042
                                  arg7,arg8,arg9,arg10,arg11)          \
2043
   do {                                                                \
2044
      volatile OrigFn        _orig = (orig);                           \
2045
      volatile unsigned long _argvec[12];                              \
2046
      volatile unsigned long _res;                                     \
2047
      _argvec[0] = (unsigned long)_orig.nraddr;                        \
2048
      _argvec[1] = (unsigned long)(arg1);                              \
2049
      _argvec[2] = (unsigned long)(arg2);                              \
2050
      _argvec[3] = (unsigned long)(arg3);                              \
2051
      _argvec[4] = (unsigned long)(arg4);                              \
2052
      _argvec[5] = (unsigned long)(arg5);                              \
2053
      _argvec[6] = (unsigned long)(arg6);                              \
2054
      _argvec[7] = (unsigned long)(arg7);                              \
2055
      _argvec[8] = (unsigned long)(arg8);                              \
2056
      _argvec[9] = (unsigned long)(arg9);                              \
2057
      _argvec[10] = (unsigned long)(arg10);                            \
2058
      _argvec[11] = (unsigned long)(arg11);                            \
2059
      __asm__ volatile(                                                \
2060
         VALGRIND_CFI_PROLOGUE                                         \
2061
         VALGRIND_ALIGN_STACK                                          \
2062
         "subq $136,%%rsp\n\t"                                         \
2063
         "pushq 88(%%rax)\n\t"                                         \
2064
         "pushq 80(%%rax)\n\t"                                         \
2065
         "pushq 72(%%rax)\n\t"                                         \
2066
         "pushq 64(%%rax)\n\t"                                         \
2067
         "pushq 56(%%rax)\n\t"                                         \
2068
         "movq 48(%%rax), %%r9\n\t"                                    \
2069
         "movq 40(%%rax), %%r8\n\t"                                    \
2070
         "movq 32(%%rax), %%rcx\n\t"                                   \
2071
         "movq 24(%%rax), %%rdx\n\t"                                   \
2072
         "movq 16(%%rax), %%rsi\n\t"                                   \
2073
         "movq 8(%%rax), %%rdi\n\t"                                    \
2074
         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
2075
         VALGRIND_CALL_NOREDIR_RAX                                     \
2076
         VALGRIND_RESTORE_STACK                                        \
2077
         VALGRIND_CFI_EPILOGUE                                         \
2078
         : /*out*/   "=a" (_res)                                       \
2079
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
2080
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2081
      );                                                               \
2082
      lval = (__typeof__(lval)) _res;                                  \
2083
   } while (0)
2084
2085
#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,       \
2086
                                arg7,arg8,arg9,arg10,arg11,arg12)      \
2087
   do {                                                                \
2088
      volatile OrigFn        _orig = (orig);                           \
2089
      volatile unsigned long _argvec[13];                              \
2090
      volatile unsigned long _res;                                     \
2091
      _argvec[0] = (unsigned long)_orig.nraddr;                        \
2092
      _argvec[1] = (unsigned long)(arg1);                              \
2093
      _argvec[2] = (unsigned long)(arg2);                              \
2094
      _argvec[3] = (unsigned long)(arg3);                              \
2095
      _argvec[4] = (unsigned long)(arg4);                              \
2096
      _argvec[5] = (unsigned long)(arg5);                              \
2097
      _argvec[6] = (unsigned long)(arg6);                              \
2098
      _argvec[7] = (unsigned long)(arg7);                              \
2099
      _argvec[8] = (unsigned long)(arg8);                              \
2100
      _argvec[9] = (unsigned long)(arg9);                              \
2101
      _argvec[10] = (unsigned long)(arg10);                            \
2102
      _argvec[11] = (unsigned long)(arg11);                            \
2103
      _argvec[12] = (unsigned long)(arg12);                            \
2104
      __asm__ volatile(                                                \
2105
         VALGRIND_CFI_PROLOGUE                                         \
2106
         VALGRIND_ALIGN_STACK                                          \
2107
         "subq $128,%%rsp\n\t"                                         \
2108
         "pushq 96(%%rax)\n\t"                                         \
2109
         "pushq 88(%%rax)\n\t"                                         \
2110
         "pushq 80(%%rax)\n\t"                                         \
2111
         "pushq 72(%%rax)\n\t"                                         \
2112
         "pushq 64(%%rax)\n\t"                                         \
2113
         "pushq 56(%%rax)\n\t"                                         \
2114
         "movq 48(%%rax), %%r9\n\t"                                    \
2115
         "movq 40(%%rax), %%r8\n\t"                                    \
2116
         "movq 32(%%rax), %%rcx\n\t"                                   \
2117
         "movq 24(%%rax), %%rdx\n\t"                                   \
2118
         "movq 16(%%rax), %%rsi\n\t"                                   \
2119
         "movq 8(%%rax), %%rdi\n\t"                                    \
2120
         "movq (%%rax), %%rax\n\t"  /* target->%rax */                 \
2121
         VALGRIND_CALL_NOREDIR_RAX                                     \
2122
         VALGRIND_RESTORE_STACK                                        \
2123
         VALGRIND_CFI_EPILOGUE                                         \
2124
         : /*out*/   "=a" (_res)                                       \
2125
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER                 \
2126
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
2127
      );                                                               \
2128
      lval = (__typeof__(lval)) _res;                                  \
2129
   } while (0)
2130
2131
#endif /* PLAT_amd64_linux || PLAT_amd64_darwin || PLAT_amd64_solaris */
2132
2133
/* ------------------------ ppc32-linux ------------------------ */
2134
2135
#if defined(PLAT_ppc32_linux)
2136
2137
/* This is useful for finding out about the on-stack stuff:
2138
2139
   extern int f9  ( int,int,int,int,int,int,int,int,int );
2140
   extern int f10 ( int,int,int,int,int,int,int,int,int,int );
2141
   extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
2142
   extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
2143
2144
   int g9 ( void ) {
2145
      return f9(11,22,33,44,55,66,77,88,99);
2146
   }
2147
   int g10 ( void ) {
2148
      return f10(11,22,33,44,55,66,77,88,99,110);
2149
   }
2150
   int g11 ( void ) {
2151
      return f11(11,22,33,44,55,66,77,88,99,110,121);
2152
   }
2153
   int g12 ( void ) {
2154
      return f12(11,22,33,44,55,66,77,88,99,110,121,132);
2155
   }
2156
*/
2157
2158
/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2159
2160
/* These regs are trashed by the hidden call. */
2161
#define __CALLER_SAVED_REGS                                       \
2162
   "lr", "ctr", "xer",                                            \
2163
   "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
2164
   "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",   \
2165
   "r11", "r12", "r13"
2166
2167
/* Macros to save and align the stack before making a function
2168
   call and restore it afterwards as gcc may not keep the stack
2169
   pointer aligned if it doesn't realise calls are being made
2170
   to other functions. */
2171
2172
#define VALGRIND_ALIGN_STACK               \
2173
      "mr 28,1\n\t"                        \
2174
      "rlwinm 1,1,0,0,27\n\t"
2175
#define VALGRIND_RESTORE_STACK             \
2176
      "mr 1,28\n\t"
2177
2178
/* These CALL_FN_ macros assume that on ppc32-linux, 
2179
   sizeof(unsigned long) == 4. */
2180
2181
#define CALL_FN_W_v(lval, orig)                                   \
2182
   do {                                                           \
2183
      volatile OrigFn        _orig = (orig);                      \
2184
      volatile unsigned long _argvec[1];                          \
2185
      volatile unsigned long _res;                                \
2186
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2187
      __asm__ volatile(                                           \
2188
         VALGRIND_ALIGN_STACK                                     \
2189
         "mr 11,%1\n\t"                                           \
2190
         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2191
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2192
         VALGRIND_RESTORE_STACK                                   \
2193
         "mr %0,3"                                                \
2194
         : /*out*/   "=r" (_res)                                  \
2195
         : /*in*/    "r" (&_argvec[0])                            \
2196
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2197
      );                                                          \
2198
      lval = (__typeof__(lval)) _res;                             \
2199
   } while (0)
2200
2201
#define CALL_FN_W_W(lval, orig, arg1)                             \
2202
   do {                                                           \
2203
      volatile OrigFn        _orig = (orig);                      \
2204
      volatile unsigned long _argvec[2];                          \
2205
      volatile unsigned long _res;                                \
2206
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2207
      _argvec[1] = (unsigned long)arg1;                           \
2208
      __asm__ volatile(                                           \
2209
         VALGRIND_ALIGN_STACK                                     \
2210
         "mr 11,%1\n\t"                                           \
2211
         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2212
         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2213
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2214
         VALGRIND_RESTORE_STACK                                   \
2215
         "mr %0,3"                                                \
2216
         : /*out*/   "=r" (_res)                                  \
2217
         : /*in*/    "r" (&_argvec[0])                            \
2218
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2219
      );                                                          \
2220
      lval = (__typeof__(lval)) _res;                             \
2221
   } while (0)
2222
2223
#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
2224
   do {                                                           \
2225
      volatile OrigFn        _orig = (orig);                      \
2226
      volatile unsigned long _argvec[3];                          \
2227
      volatile unsigned long _res;                                \
2228
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2229
      _argvec[1] = (unsigned long)arg1;                           \
2230
      _argvec[2] = (unsigned long)arg2;                           \
2231
      __asm__ volatile(                                           \
2232
         VALGRIND_ALIGN_STACK                                     \
2233
         "mr 11,%1\n\t"                                           \
2234
         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2235
         "lwz 4,8(11)\n\t"                                        \
2236
         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2237
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2238
         VALGRIND_RESTORE_STACK                                   \
2239
         "mr %0,3"                                                \
2240
         : /*out*/   "=r" (_res)                                  \
2241
         : /*in*/    "r" (&_argvec[0])                            \
2242
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2243
      );                                                          \
2244
      lval = (__typeof__(lval)) _res;                             \
2245
   } while (0)
2246
2247
#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
2248
   do {                                                           \
2249
      volatile OrigFn        _orig = (orig);                      \
2250
      volatile unsigned long _argvec[4];                          \
2251
      volatile unsigned long _res;                                \
2252
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2253
      _argvec[1] = (unsigned long)arg1;                           \
2254
      _argvec[2] = (unsigned long)arg2;                           \
2255
      _argvec[3] = (unsigned long)arg3;                           \
2256
      __asm__ volatile(                                           \
2257
         VALGRIND_ALIGN_STACK                                     \
2258
         "mr 11,%1\n\t"                                           \
2259
         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2260
         "lwz 4,8(11)\n\t"                                        \
2261
         "lwz 5,12(11)\n\t"                                       \
2262
         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2263
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2264
         VALGRIND_RESTORE_STACK                                   \
2265
         "mr %0,3"                                                \
2266
         : /*out*/   "=r" (_res)                                  \
2267
         : /*in*/    "r" (&_argvec[0])                            \
2268
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2269
      );                                                          \
2270
      lval = (__typeof__(lval)) _res;                             \
2271
   } while (0)
2272
2273
#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
2274
   do {                                                           \
2275
      volatile OrigFn        _orig = (orig);                      \
2276
      volatile unsigned long _argvec[5];                          \
2277
      volatile unsigned long _res;                                \
2278
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2279
      _argvec[1] = (unsigned long)arg1;                           \
2280
      _argvec[2] = (unsigned long)arg2;                           \
2281
      _argvec[3] = (unsigned long)arg3;                           \
2282
      _argvec[4] = (unsigned long)arg4;                           \
2283
      __asm__ volatile(                                           \
2284
         VALGRIND_ALIGN_STACK                                     \
2285
         "mr 11,%1\n\t"                                           \
2286
         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2287
         "lwz 4,8(11)\n\t"                                        \
2288
         "lwz 5,12(11)\n\t"                                       \
2289
         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2290
         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2291
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2292
         VALGRIND_RESTORE_STACK                                   \
2293
         "mr %0,3"                                                \
2294
         : /*out*/   "=r" (_res)                                  \
2295
         : /*in*/    "r" (&_argvec[0])                            \
2296
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2297
      );                                                          \
2298
      lval = (__typeof__(lval)) _res;                             \
2299
   } while (0)
2300
2301
#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
2302
   do {                                                           \
2303
      volatile OrigFn        _orig = (orig);                      \
2304
      volatile unsigned long _argvec[6];                          \
2305
      volatile unsigned long _res;                                \
2306
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2307
      _argvec[1] = (unsigned long)arg1;                           \
2308
      _argvec[2] = (unsigned long)arg2;                           \
2309
      _argvec[3] = (unsigned long)arg3;                           \
2310
      _argvec[4] = (unsigned long)arg4;                           \
2311
      _argvec[5] = (unsigned long)arg5;                           \
2312
      __asm__ volatile(                                           \
2313
         VALGRIND_ALIGN_STACK                                     \
2314
         "mr 11,%1\n\t"                                           \
2315
         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2316
         "lwz 4,8(11)\n\t"                                        \
2317
         "lwz 5,12(11)\n\t"                                       \
2318
         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2319
         "lwz 7,20(11)\n\t"                                       \
2320
         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2321
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2322
         VALGRIND_RESTORE_STACK                                   \
2323
         "mr %0,3"                                                \
2324
         : /*out*/   "=r" (_res)                                  \
2325
         : /*in*/    "r" (&_argvec[0])                            \
2326
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2327
      );                                                          \
2328
      lval = (__typeof__(lval)) _res;                             \
2329
   } while (0)
2330
2331
#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
2332
   do {                                                           \
2333
      volatile OrigFn        _orig = (orig);                      \
2334
      volatile unsigned long _argvec[7];                          \
2335
      volatile unsigned long _res;                                \
2336
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2337
      _argvec[1] = (unsigned long)arg1;                           \
2338
      _argvec[2] = (unsigned long)arg2;                           \
2339
      _argvec[3] = (unsigned long)arg3;                           \
2340
      _argvec[4] = (unsigned long)arg4;                           \
2341
      _argvec[5] = (unsigned long)arg5;                           \
2342
      _argvec[6] = (unsigned long)arg6;                           \
2343
      __asm__ volatile(                                           \
2344
         VALGRIND_ALIGN_STACK                                     \
2345
         "mr 11,%1\n\t"                                           \
2346
         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2347
         "lwz 4,8(11)\n\t"                                        \
2348
         "lwz 5,12(11)\n\t"                                       \
2349
         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2350
         "lwz 7,20(11)\n\t"                                       \
2351
         "lwz 8,24(11)\n\t"                                       \
2352
         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2353
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2354
         VALGRIND_RESTORE_STACK                                   \
2355
         "mr %0,3"                                                \
2356
         : /*out*/   "=r" (_res)                                  \
2357
         : /*in*/    "r" (&_argvec[0])                            \
2358
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2359
      );                                                          \
2360
      lval = (__typeof__(lval)) _res;                             \
2361
   } while (0)
2362
2363
#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2364
                                 arg7)                            \
2365
   do {                                                           \
2366
      volatile OrigFn        _orig = (orig);                      \
2367
      volatile unsigned long _argvec[8];                          \
2368
      volatile unsigned long _res;                                \
2369
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2370
      _argvec[1] = (unsigned long)arg1;                           \
2371
      _argvec[2] = (unsigned long)arg2;                           \
2372
      _argvec[3] = (unsigned long)arg3;                           \
2373
      _argvec[4] = (unsigned long)arg4;                           \
2374
      _argvec[5] = (unsigned long)arg5;                           \
2375
      _argvec[6] = (unsigned long)arg6;                           \
2376
      _argvec[7] = (unsigned long)arg7;                           \
2377
      __asm__ volatile(                                           \
2378
         VALGRIND_ALIGN_STACK                                     \
2379
         "mr 11,%1\n\t"                                           \
2380
         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2381
         "lwz 4,8(11)\n\t"                                        \
2382
         "lwz 5,12(11)\n\t"                                       \
2383
         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2384
         "lwz 7,20(11)\n\t"                                       \
2385
         "lwz 8,24(11)\n\t"                                       \
2386
         "lwz 9,28(11)\n\t"                                       \
2387
         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2388
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2389
         VALGRIND_RESTORE_STACK                                   \
2390
         "mr %0,3"                                                \
2391
         : /*out*/   "=r" (_res)                                  \
2392
         : /*in*/    "r" (&_argvec[0])                            \
2393
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2394
      );                                                          \
2395
      lval = (__typeof__(lval)) _res;                             \
2396
   } while (0)
2397
2398
#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2399
                                 arg7,arg8)                       \
2400
   do {                                                           \
2401
      volatile OrigFn        _orig = (orig);                      \
2402
      volatile unsigned long _argvec[9];                          \
2403
      volatile unsigned long _res;                                \
2404
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2405
      _argvec[1] = (unsigned long)arg1;                           \
2406
      _argvec[2] = (unsigned long)arg2;                           \
2407
      _argvec[3] = (unsigned long)arg3;                           \
2408
      _argvec[4] = (unsigned long)arg4;                           \
2409
      _argvec[5] = (unsigned long)arg5;                           \
2410
      _argvec[6] = (unsigned long)arg6;                           \
2411
      _argvec[7] = (unsigned long)arg7;                           \
2412
      _argvec[8] = (unsigned long)arg8;                           \
2413
      __asm__ volatile(                                           \
2414
         VALGRIND_ALIGN_STACK                                     \
2415
         "mr 11,%1\n\t"                                           \
2416
         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2417
         "lwz 4,8(11)\n\t"                                        \
2418
         "lwz 5,12(11)\n\t"                                       \
2419
         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2420
         "lwz 7,20(11)\n\t"                                       \
2421
         "lwz 8,24(11)\n\t"                                       \
2422
         "lwz 9,28(11)\n\t"                                       \
2423
         "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
2424
         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2425
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2426
         VALGRIND_RESTORE_STACK                                   \
2427
         "mr %0,3"                                                \
2428
         : /*out*/   "=r" (_res)                                  \
2429
         : /*in*/    "r" (&_argvec[0])                            \
2430
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2431
      );                                                          \
2432
      lval = (__typeof__(lval)) _res;                             \
2433
   } while (0)
2434
2435
#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2436
                                 arg7,arg8,arg9)                  \
2437
   do {                                                           \
2438
      volatile OrigFn        _orig = (orig);                      \
2439
      volatile unsigned long _argvec[10];                         \
2440
      volatile unsigned long _res;                                \
2441
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2442
      _argvec[1] = (unsigned long)arg1;                           \
2443
      _argvec[2] = (unsigned long)arg2;                           \
2444
      _argvec[3] = (unsigned long)arg3;                           \
2445
      _argvec[4] = (unsigned long)arg4;                           \
2446
      _argvec[5] = (unsigned long)arg5;                           \
2447
      _argvec[6] = (unsigned long)arg6;                           \
2448
      _argvec[7] = (unsigned long)arg7;                           \
2449
      _argvec[8] = (unsigned long)arg8;                           \
2450
      _argvec[9] = (unsigned long)arg9;                           \
2451
      __asm__ volatile(                                           \
2452
         VALGRIND_ALIGN_STACK                                     \
2453
         "mr 11,%1\n\t"                                           \
2454
         "addi 1,1,-16\n\t"                                       \
2455
         /* arg9 */                                               \
2456
         "lwz 3,36(11)\n\t"                                       \
2457
         "stw 3,8(1)\n\t"                                         \
2458
         /* args1-8 */                                            \
2459
         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2460
         "lwz 4,8(11)\n\t"                                        \
2461
         "lwz 5,12(11)\n\t"                                       \
2462
         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2463
         "lwz 7,20(11)\n\t"                                       \
2464
         "lwz 8,24(11)\n\t"                                       \
2465
         "lwz 9,28(11)\n\t"                                       \
2466
         "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
2467
         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2468
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2469
         VALGRIND_RESTORE_STACK                                   \
2470
         "mr %0,3"                                                \
2471
         : /*out*/   "=r" (_res)                                  \
2472
         : /*in*/    "r" (&_argvec[0])                            \
2473
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2474
      );                                                          \
2475
      lval = (__typeof__(lval)) _res;                             \
2476
   } while (0)
2477
2478
#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
2479
                                  arg7,arg8,arg9,arg10)           \
2480
   do {                                                           \
2481
      volatile OrigFn        _orig = (orig);                      \
2482
      volatile unsigned long _argvec[11];                         \
2483
      volatile unsigned long _res;                                \
2484
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2485
      _argvec[1] = (unsigned long)arg1;                           \
2486
      _argvec[2] = (unsigned long)arg2;                           \
2487
      _argvec[3] = (unsigned long)arg3;                           \
2488
      _argvec[4] = (unsigned long)arg4;                           \
2489
      _argvec[5] = (unsigned long)arg5;                           \
2490
      _argvec[6] = (unsigned long)arg6;                           \
2491
      _argvec[7] = (unsigned long)arg7;                           \
2492
      _argvec[8] = (unsigned long)arg8;                           \
2493
      _argvec[9] = (unsigned long)arg9;                           \
2494
      _argvec[10] = (unsigned long)arg10;                         \
2495
      __asm__ volatile(                                           \
2496
         VALGRIND_ALIGN_STACK                                     \
2497
         "mr 11,%1\n\t"                                           \
2498
         "addi 1,1,-16\n\t"                                       \
2499
         /* arg10 */                                              \
2500
         "lwz 3,40(11)\n\t"                                       \
2501
         "stw 3,12(1)\n\t"                                        \
2502
         /* arg9 */                                               \
2503
         "lwz 3,36(11)\n\t"                                       \
2504
         "stw 3,8(1)\n\t"                                         \
2505
         /* args1-8 */                                            \
2506
         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2507
         "lwz 4,8(11)\n\t"                                        \
2508
         "lwz 5,12(11)\n\t"                                       \
2509
         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2510
         "lwz 7,20(11)\n\t"                                       \
2511
         "lwz 8,24(11)\n\t"                                       \
2512
         "lwz 9,28(11)\n\t"                                       \
2513
         "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
2514
         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2515
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2516
         VALGRIND_RESTORE_STACK                                   \
2517
         "mr %0,3"                                                \
2518
         : /*out*/   "=r" (_res)                                  \
2519
         : /*in*/    "r" (&_argvec[0])                            \
2520
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2521
      );                                                          \
2522
      lval = (__typeof__(lval)) _res;                             \
2523
   } while (0)
2524
2525
#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
2526
                                  arg7,arg8,arg9,arg10,arg11)     \
2527
   do {                                                           \
2528
      volatile OrigFn        _orig = (orig);                      \
2529
      volatile unsigned long _argvec[12];                         \
2530
      volatile unsigned long _res;                                \
2531
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2532
      _argvec[1] = (unsigned long)arg1;                           \
2533
      _argvec[2] = (unsigned long)arg2;                           \
2534
      _argvec[3] = (unsigned long)arg3;                           \
2535
      _argvec[4] = (unsigned long)arg4;                           \
2536
      _argvec[5] = (unsigned long)arg5;                           \
2537
      _argvec[6] = (unsigned long)arg6;                           \
2538
      _argvec[7] = (unsigned long)arg7;                           \
2539
      _argvec[8] = (unsigned long)arg8;                           \
2540
      _argvec[9] = (unsigned long)arg9;                           \
2541
      _argvec[10] = (unsigned long)arg10;                         \
2542
      _argvec[11] = (unsigned long)arg11;                         \
2543
      __asm__ volatile(                                           \
2544
         VALGRIND_ALIGN_STACK                                     \
2545
         "mr 11,%1\n\t"                                           \
2546
         "addi 1,1,-32\n\t"                                       \
2547
         /* arg11 */                                              \
2548
         "lwz 3,44(11)\n\t"                                       \
2549
         "stw 3,16(1)\n\t"                                        \
2550
         /* arg10 */                                              \
2551
         "lwz 3,40(11)\n\t"                                       \
2552
         "stw 3,12(1)\n\t"                                        \
2553
         /* arg9 */                                               \
2554
         "lwz 3,36(11)\n\t"                                       \
2555
         "stw 3,8(1)\n\t"                                         \
2556
         /* args1-8 */                                            \
2557
         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2558
         "lwz 4,8(11)\n\t"                                        \
2559
         "lwz 5,12(11)\n\t"                                       \
2560
         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2561
         "lwz 7,20(11)\n\t"                                       \
2562
         "lwz 8,24(11)\n\t"                                       \
2563
         "lwz 9,28(11)\n\t"                                       \
2564
         "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
2565
         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2566
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2567
         VALGRIND_RESTORE_STACK                                   \
2568
         "mr %0,3"                                                \
2569
         : /*out*/   "=r" (_res)                                  \
2570
         : /*in*/    "r" (&_argvec[0])                            \
2571
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2572
      );                                                          \
2573
      lval = (__typeof__(lval)) _res;                             \
2574
   } while (0)
2575
2576
#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
2577
                                arg7,arg8,arg9,arg10,arg11,arg12) \
2578
   do {                                                           \
2579
      volatile OrigFn        _orig = (orig);                      \
2580
      volatile unsigned long _argvec[13];                         \
2581
      volatile unsigned long _res;                                \
2582
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
2583
      _argvec[1] = (unsigned long)arg1;                           \
2584
      _argvec[2] = (unsigned long)arg2;                           \
2585
      _argvec[3] = (unsigned long)arg3;                           \
2586
      _argvec[4] = (unsigned long)arg4;                           \
2587
      _argvec[5] = (unsigned long)arg5;                           \
2588
      _argvec[6] = (unsigned long)arg6;                           \
2589
      _argvec[7] = (unsigned long)arg7;                           \
2590
      _argvec[8] = (unsigned long)arg8;                           \
2591
      _argvec[9] = (unsigned long)arg9;                           \
2592
      _argvec[10] = (unsigned long)arg10;                         \
2593
      _argvec[11] = (unsigned long)arg11;                         \
2594
      _argvec[12] = (unsigned long)arg12;                         \
2595
      __asm__ volatile(                                           \
2596
         VALGRIND_ALIGN_STACK                                     \
2597
         "mr 11,%1\n\t"                                           \
2598
         "addi 1,1,-32\n\t"                                       \
2599
         /* arg12 */                                              \
2600
         "lwz 3,48(11)\n\t"                                       \
2601
         "stw 3,20(1)\n\t"                                        \
2602
         /* arg11 */                                              \
2603
         "lwz 3,44(11)\n\t"                                       \
2604
         "stw 3,16(1)\n\t"                                        \
2605
         /* arg10 */                                              \
2606
         "lwz 3,40(11)\n\t"                                       \
2607
         "stw 3,12(1)\n\t"                                        \
2608
         /* arg9 */                                               \
2609
         "lwz 3,36(11)\n\t"                                       \
2610
         "stw 3,8(1)\n\t"                                         \
2611
         /* args1-8 */                                            \
2612
         "lwz 3,4(11)\n\t"   /* arg1->r3 */                       \
2613
         "lwz 4,8(11)\n\t"                                        \
2614
         "lwz 5,12(11)\n\t"                                       \
2615
         "lwz 6,16(11)\n\t"  /* arg4->r6 */                       \
2616
         "lwz 7,20(11)\n\t"                                       \
2617
         "lwz 8,24(11)\n\t"                                       \
2618
         "lwz 9,28(11)\n\t"                                       \
2619
         "lwz 10,32(11)\n\t" /* arg8->r10 */                      \
2620
         "lwz 11,0(11)\n\t"  /* target->r11 */                    \
2621
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2622
         VALGRIND_RESTORE_STACK                                   \
2623
         "mr %0,3"                                                \
2624
         : /*out*/   "=r" (_res)                                  \
2625
         : /*in*/    "r" (&_argvec[0])                            \
2626
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2627
      );                                                          \
2628
      lval = (__typeof__(lval)) _res;                             \
2629
   } while (0)
2630
2631
#endif /* PLAT_ppc32_linux */
2632
2633
/* ------------------------ ppc64-linux ------------------------ */
2634
2635
#if defined(PLAT_ppc64be_linux)
2636
2637
/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
2638
2639
/* These regs are trashed by the hidden call. */
2640
#define __CALLER_SAVED_REGS                                       \
2641
   "lr", "ctr", "xer",                                            \
2642
   "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
2643
   "r0", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",         \
2644
   "r11", "r12", "r13"
2645
2646
/* Macros to save and align the stack before making a function
2647
   call and restore it afterwards as gcc may not keep the stack
2648
   pointer aligned if it doesn't realise calls are being made
2649
   to other functions. */
2650
2651
#define VALGRIND_ALIGN_STACK               \
2652
      "mr 28,1\n\t"                        \
2653
      "rldicr 1,1,0,59\n\t"
2654
#define VALGRIND_RESTORE_STACK             \
2655
      "mr 1,28\n\t"
2656
2657
/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
2658
   long) == 8. */
2659
2660
#define CALL_FN_W_v(lval, orig)                                   \
2661
   do {                                                           \
2662
      volatile OrigFn        _orig = (orig);                      \
2663
      volatile unsigned long _argvec[3+0];                        \
2664
      volatile unsigned long _res;                                \
2665
      /* _argvec[0] holds current r2 across the call */           \
2666
      _argvec[1] = (unsigned long)_orig.r2;                       \
2667
      _argvec[2] = (unsigned long)_orig.nraddr;                   \
2668
      __asm__ volatile(                                           \
2669
         VALGRIND_ALIGN_STACK                                     \
2670
         "mr 11,%1\n\t"                                           \
2671
         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2672
         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2673
         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2674
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2675
         "mr 11,%1\n\t"                                           \
2676
         "mr %0,3\n\t"                                            \
2677
         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2678
         VALGRIND_RESTORE_STACK                                   \
2679
         : /*out*/   "=r" (_res)                                  \
2680
         : /*in*/    "r" (&_argvec[2])                            \
2681
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2682
      );                                                          \
2683
      lval = (__typeof__(lval)) _res;                             \
2684
   } while (0)
2685
2686
#define CALL_FN_W_W(lval, orig, arg1)                             \
2687
   do {                                                           \
2688
      volatile OrigFn        _orig = (orig);                      \
2689
      volatile unsigned long _argvec[3+1];                        \
2690
      volatile unsigned long _res;                                \
2691
      /* _argvec[0] holds current r2 across the call */           \
2692
      _argvec[1]   = (unsigned long)_orig.r2;                     \
2693
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2694
      _argvec[2+1] = (unsigned long)arg1;                         \
2695
      __asm__ volatile(                                           \
2696
         VALGRIND_ALIGN_STACK                                     \
2697
         "mr 11,%1\n\t"                                           \
2698
         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2699
         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2700
         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2701
         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2702
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2703
         "mr 11,%1\n\t"                                           \
2704
         "mr %0,3\n\t"                                            \
2705
         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2706
         VALGRIND_RESTORE_STACK                                   \
2707
         : /*out*/   "=r" (_res)                                  \
2708
         : /*in*/    "r" (&_argvec[2])                            \
2709
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2710
      );                                                          \
2711
      lval = (__typeof__(lval)) _res;                             \
2712
   } while (0)
2713
2714
#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
2715
   do {                                                           \
2716
      volatile OrigFn        _orig = (orig);                      \
2717
      volatile unsigned long _argvec[3+2];                        \
2718
      volatile unsigned long _res;                                \
2719
      /* _argvec[0] holds current r2 across the call */           \
2720
      _argvec[1]   = (unsigned long)_orig.r2;                     \
2721
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2722
      _argvec[2+1] = (unsigned long)arg1;                         \
2723
      _argvec[2+2] = (unsigned long)arg2;                         \
2724
      __asm__ volatile(                                           \
2725
         VALGRIND_ALIGN_STACK                                     \
2726
         "mr 11,%1\n\t"                                           \
2727
         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2728
         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2729
         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2730
         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2731
         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2732
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2733
         "mr 11,%1\n\t"                                           \
2734
         "mr %0,3\n\t"                                            \
2735
         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2736
         VALGRIND_RESTORE_STACK                                   \
2737
         : /*out*/   "=r" (_res)                                  \
2738
         : /*in*/    "r" (&_argvec[2])                            \
2739
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2740
      );                                                          \
2741
      lval = (__typeof__(lval)) _res;                             \
2742
   } while (0)
2743
2744
#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
2745
   do {                                                           \
2746
      volatile OrigFn        _orig = (orig);                      \
2747
      volatile unsigned long _argvec[3+3];                        \
2748
      volatile unsigned long _res;                                \
2749
      /* _argvec[0] holds current r2 across the call */           \
2750
      _argvec[1]   = (unsigned long)_orig.r2;                     \
2751
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2752
      _argvec[2+1] = (unsigned long)arg1;                         \
2753
      _argvec[2+2] = (unsigned long)arg2;                         \
2754
      _argvec[2+3] = (unsigned long)arg3;                         \
2755
      __asm__ volatile(                                           \
2756
         VALGRIND_ALIGN_STACK                                     \
2757
         "mr 11,%1\n\t"                                           \
2758
         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2759
         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2760
         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2761
         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2762
         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2763
         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2764
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2765
         "mr 11,%1\n\t"                                           \
2766
         "mr %0,3\n\t"                                            \
2767
         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2768
         VALGRIND_RESTORE_STACK                                   \
2769
         : /*out*/   "=r" (_res)                                  \
2770
         : /*in*/    "r" (&_argvec[2])                            \
2771
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2772
      );                                                          \
2773
      lval = (__typeof__(lval)) _res;                             \
2774
   } while (0)
2775
2776
#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
2777
   do {                                                           \
2778
      volatile OrigFn        _orig = (orig);                      \
2779
      volatile unsigned long _argvec[3+4];                        \
2780
      volatile unsigned long _res;                                \
2781
      /* _argvec[0] holds current r2 across the call */           \
2782
      _argvec[1]   = (unsigned long)_orig.r2;                     \
2783
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2784
      _argvec[2+1] = (unsigned long)arg1;                         \
2785
      _argvec[2+2] = (unsigned long)arg2;                         \
2786
      _argvec[2+3] = (unsigned long)arg3;                         \
2787
      _argvec[2+4] = (unsigned long)arg4;                         \
2788
      __asm__ volatile(                                           \
2789
         VALGRIND_ALIGN_STACK                                     \
2790
         "mr 11,%1\n\t"                                           \
2791
         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2792
         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2793
         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2794
         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2795
         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2796
         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2797
         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2798
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2799
         "mr 11,%1\n\t"                                           \
2800
         "mr %0,3\n\t"                                            \
2801
         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2802
         VALGRIND_RESTORE_STACK                                   \
2803
         : /*out*/   "=r" (_res)                                  \
2804
         : /*in*/    "r" (&_argvec[2])                            \
2805
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2806
      );                                                          \
2807
      lval = (__typeof__(lval)) _res;                             \
2808
   } while (0)
2809
2810
#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
2811
   do {                                                           \
2812
      volatile OrigFn        _orig = (orig);                      \
2813
      volatile unsigned long _argvec[3+5];                        \
2814
      volatile unsigned long _res;                                \
2815
      /* _argvec[0] holds current r2 across the call */           \
2816
      _argvec[1]   = (unsigned long)_orig.r2;                     \
2817
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2818
      _argvec[2+1] = (unsigned long)arg1;                         \
2819
      _argvec[2+2] = (unsigned long)arg2;                         \
2820
      _argvec[2+3] = (unsigned long)arg3;                         \
2821
      _argvec[2+4] = (unsigned long)arg4;                         \
2822
      _argvec[2+5] = (unsigned long)arg5;                         \
2823
      __asm__ volatile(                                           \
2824
         VALGRIND_ALIGN_STACK                                     \
2825
         "mr 11,%1\n\t"                                           \
2826
         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2827
         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2828
         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2829
         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2830
         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2831
         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2832
         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2833
         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2834
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2835
         "mr 11,%1\n\t"                                           \
2836
         "mr %0,3\n\t"                                            \
2837
         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2838
         VALGRIND_RESTORE_STACK                                   \
2839
         : /*out*/   "=r" (_res)                                  \
2840
         : /*in*/    "r" (&_argvec[2])                            \
2841
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2842
      );                                                          \
2843
      lval = (__typeof__(lval)) _res;                             \
2844
   } while (0)
2845
2846
#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
2847
   do {                                                           \
2848
      volatile OrigFn        _orig = (orig);                      \
2849
      volatile unsigned long _argvec[3+6];                        \
2850
      volatile unsigned long _res;                                \
2851
      /* _argvec[0] holds current r2 across the call */           \
2852
      _argvec[1]   = (unsigned long)_orig.r2;                     \
2853
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2854
      _argvec[2+1] = (unsigned long)arg1;                         \
2855
      _argvec[2+2] = (unsigned long)arg2;                         \
2856
      _argvec[2+3] = (unsigned long)arg3;                         \
2857
      _argvec[2+4] = (unsigned long)arg4;                         \
2858
      _argvec[2+5] = (unsigned long)arg5;                         \
2859
      _argvec[2+6] = (unsigned long)arg6;                         \
2860
      __asm__ volatile(                                           \
2861
         VALGRIND_ALIGN_STACK                                     \
2862
         "mr 11,%1\n\t"                                           \
2863
         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2864
         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2865
         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2866
         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2867
         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2868
         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2869
         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2870
         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
2871
         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2872
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2873
         "mr 11,%1\n\t"                                           \
2874
         "mr %0,3\n\t"                                            \
2875
         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2876
         VALGRIND_RESTORE_STACK                                   \
2877
         : /*out*/   "=r" (_res)                                  \
2878
         : /*in*/    "r" (&_argvec[2])                            \
2879
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2880
      );                                                          \
2881
      lval = (__typeof__(lval)) _res;                             \
2882
   } while (0)
2883
2884
#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2885
                                 arg7)                            \
2886
   do {                                                           \
2887
      volatile OrigFn        _orig = (orig);                      \
2888
      volatile unsigned long _argvec[3+7];                        \
2889
      volatile unsigned long _res;                                \
2890
      /* _argvec[0] holds current r2 across the call */           \
2891
      _argvec[1]   = (unsigned long)_orig.r2;                     \
2892
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2893
      _argvec[2+1] = (unsigned long)arg1;                         \
2894
      _argvec[2+2] = (unsigned long)arg2;                         \
2895
      _argvec[2+3] = (unsigned long)arg3;                         \
2896
      _argvec[2+4] = (unsigned long)arg4;                         \
2897
      _argvec[2+5] = (unsigned long)arg5;                         \
2898
      _argvec[2+6] = (unsigned long)arg6;                         \
2899
      _argvec[2+7] = (unsigned long)arg7;                         \
2900
      __asm__ volatile(                                           \
2901
         VALGRIND_ALIGN_STACK                                     \
2902
         "mr 11,%1\n\t"                                           \
2903
         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2904
         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2905
         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2906
         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2907
         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2908
         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2909
         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2910
         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
2911
         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
2912
         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2913
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2914
         "mr 11,%1\n\t"                                           \
2915
         "mr %0,3\n\t"                                            \
2916
         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2917
         VALGRIND_RESTORE_STACK                                   \
2918
         : /*out*/   "=r" (_res)                                  \
2919
         : /*in*/    "r" (&_argvec[2])                            \
2920
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2921
      );                                                          \
2922
      lval = (__typeof__(lval)) _res;                             \
2923
   } while (0)
2924
2925
#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2926
                                 arg7,arg8)                       \
2927
   do {                                                           \
2928
      volatile OrigFn        _orig = (orig);                      \
2929
      volatile unsigned long _argvec[3+8];                        \
2930
      volatile unsigned long _res;                                \
2931
      /* _argvec[0] holds current r2 across the call */           \
2932
      _argvec[1]   = (unsigned long)_orig.r2;                     \
2933
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2934
      _argvec[2+1] = (unsigned long)arg1;                         \
2935
      _argvec[2+2] = (unsigned long)arg2;                         \
2936
      _argvec[2+3] = (unsigned long)arg3;                         \
2937
      _argvec[2+4] = (unsigned long)arg4;                         \
2938
      _argvec[2+5] = (unsigned long)arg5;                         \
2939
      _argvec[2+6] = (unsigned long)arg6;                         \
2940
      _argvec[2+7] = (unsigned long)arg7;                         \
2941
      _argvec[2+8] = (unsigned long)arg8;                         \
2942
      __asm__ volatile(                                           \
2943
         VALGRIND_ALIGN_STACK                                     \
2944
         "mr 11,%1\n\t"                                           \
2945
         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2946
         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2947
         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2948
         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2949
         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2950
         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
2951
         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
2952
         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
2953
         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
2954
         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
2955
         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
2956
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
2957
         "mr 11,%1\n\t"                                           \
2958
         "mr %0,3\n\t"                                            \
2959
         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
2960
         VALGRIND_RESTORE_STACK                                   \
2961
         : /*out*/   "=r" (_res)                                  \
2962
         : /*in*/    "r" (&_argvec[2])                            \
2963
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
2964
      );                                                          \
2965
      lval = (__typeof__(lval)) _res;                             \
2966
   } while (0)
2967
2968
#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
2969
                                 arg7,arg8,arg9)                  \
2970
   do {                                                           \
2971
      volatile OrigFn        _orig = (orig);                      \
2972
      volatile unsigned long _argvec[3+9];                        \
2973
      volatile unsigned long _res;                                \
2974
      /* _argvec[0] holds current r2 across the call */           \
2975
      _argvec[1]   = (unsigned long)_orig.r2;                     \
2976
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
2977
      _argvec[2+1] = (unsigned long)arg1;                         \
2978
      _argvec[2+2] = (unsigned long)arg2;                         \
2979
      _argvec[2+3] = (unsigned long)arg3;                         \
2980
      _argvec[2+4] = (unsigned long)arg4;                         \
2981
      _argvec[2+5] = (unsigned long)arg5;                         \
2982
      _argvec[2+6] = (unsigned long)arg6;                         \
2983
      _argvec[2+7] = (unsigned long)arg7;                         \
2984
      _argvec[2+8] = (unsigned long)arg8;                         \
2985
      _argvec[2+9] = (unsigned long)arg9;                         \
2986
      __asm__ volatile(                                           \
2987
         VALGRIND_ALIGN_STACK                                     \
2988
         "mr 11,%1\n\t"                                           \
2989
         "std 2,-16(11)\n\t"  /* save tocptr */                   \
2990
         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
2991
         "addi 1,1,-128\n\t"  /* expand stack frame */            \
2992
         /* arg9 */                                               \
2993
         "ld  3,72(11)\n\t"                                       \
2994
         "std 3,112(1)\n\t"                                       \
2995
         /* args1-8 */                                            \
2996
         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
2997
         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
2998
         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
2999
         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3000
         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3001
         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3002
         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
3003
         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
3004
         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3005
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3006
         "mr 11,%1\n\t"                                           \
3007
         "mr %0,3\n\t"                                            \
3008
         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
3009
         VALGRIND_RESTORE_STACK                                   \
3010
         : /*out*/   "=r" (_res)                                  \
3011
         : /*in*/    "r" (&_argvec[2])                            \
3012
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3013
      );                                                          \
3014
      lval = (__typeof__(lval)) _res;                             \
3015
   } while (0)
3016
3017
#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3018
                                  arg7,arg8,arg9,arg10)           \
3019
   do {                                                           \
3020
      volatile OrigFn        _orig = (orig);                      \
3021
      volatile unsigned long _argvec[3+10];                       \
3022
      volatile unsigned long _res;                                \
3023
      /* _argvec[0] holds current r2 across the call */           \
3024
      _argvec[1]   = (unsigned long)_orig.r2;                     \
3025
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3026
      _argvec[2+1] = (unsigned long)arg1;                         \
3027
      _argvec[2+2] = (unsigned long)arg2;                         \
3028
      _argvec[2+3] = (unsigned long)arg3;                         \
3029
      _argvec[2+4] = (unsigned long)arg4;                         \
3030
      _argvec[2+5] = (unsigned long)arg5;                         \
3031
      _argvec[2+6] = (unsigned long)arg6;                         \
3032
      _argvec[2+7] = (unsigned long)arg7;                         \
3033
      _argvec[2+8] = (unsigned long)arg8;                         \
3034
      _argvec[2+9] = (unsigned long)arg9;                         \
3035
      _argvec[2+10] = (unsigned long)arg10;                       \
3036
      __asm__ volatile(                                           \
3037
         VALGRIND_ALIGN_STACK                                     \
3038
         "mr 11,%1\n\t"                                           \
3039
         "std 2,-16(11)\n\t"  /* save tocptr */                   \
3040
         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3041
         "addi 1,1,-128\n\t"  /* expand stack frame */            \
3042
         /* arg10 */                                              \
3043
         "ld  3,80(11)\n\t"                                       \
3044
         "std 3,120(1)\n\t"                                       \
3045
         /* arg9 */                                               \
3046
         "ld  3,72(11)\n\t"                                       \
3047
         "std 3,112(1)\n\t"                                       \
3048
         /* args1-8 */                                            \
3049
         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3050
         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3051
         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3052
         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3053
         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3054
         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3055
         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
3056
         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
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
         VALGRIND_RESTORE_STACK                                   \
3063
         : /*out*/   "=r" (_res)                                  \
3064
         : /*in*/    "r" (&_argvec[2])                            \
3065
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3066
      );                                                          \
3067
      lval = (__typeof__(lval)) _res;                             \
3068
   } while (0)
3069
3070
#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3071
                                  arg7,arg8,arg9,arg10,arg11)     \
3072
   do {                                                           \
3073
      volatile OrigFn        _orig = (orig);                      \
3074
      volatile unsigned long _argvec[3+11];                       \
3075
      volatile unsigned long _res;                                \
3076
      /* _argvec[0] holds current r2 across the call */           \
3077
      _argvec[1]   = (unsigned long)_orig.r2;                     \
3078
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3079
      _argvec[2+1] = (unsigned long)arg1;                         \
3080
      _argvec[2+2] = (unsigned long)arg2;                         \
3081
      _argvec[2+3] = (unsigned long)arg3;                         \
3082
      _argvec[2+4] = (unsigned long)arg4;                         \
3083
      _argvec[2+5] = (unsigned long)arg5;                         \
3084
      _argvec[2+6] = (unsigned long)arg6;                         \
3085
      _argvec[2+7] = (unsigned long)arg7;                         \
3086
      _argvec[2+8] = (unsigned long)arg8;                         \
3087
      _argvec[2+9] = (unsigned long)arg9;                         \
3088
      _argvec[2+10] = (unsigned long)arg10;                       \
3089
      _argvec[2+11] = (unsigned long)arg11;                       \
3090
      __asm__ volatile(                                           \
3091
         VALGRIND_ALIGN_STACK                                     \
3092
         "mr 11,%1\n\t"                                           \
3093
         "std 2,-16(11)\n\t"  /* save tocptr */                   \
3094
         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3095
         "addi 1,1,-144\n\t"  /* expand stack frame */            \
3096
         /* arg11 */                                              \
3097
         "ld  3,88(11)\n\t"                                       \
3098
         "std 3,128(1)\n\t"                                       \
3099
         /* arg10 */                                              \
3100
         "ld  3,80(11)\n\t"                                       \
3101
         "std 3,120(1)\n\t"                                       \
3102
         /* arg9 */                                               \
3103
         "ld  3,72(11)\n\t"                                       \
3104
         "std 3,112(1)\n\t"                                       \
3105
         /* args1-8 */                                            \
3106
         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3107
         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3108
         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3109
         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3110
         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3111
         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3112
         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
3113
         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
3114
         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3115
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3116
         "mr 11,%1\n\t"                                           \
3117
         "mr %0,3\n\t"                                            \
3118
         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
3119
         VALGRIND_RESTORE_STACK                                   \
3120
         : /*out*/   "=r" (_res)                                  \
3121
         : /*in*/    "r" (&_argvec[2])                            \
3122
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3123
      );                                                          \
3124
      lval = (__typeof__(lval)) _res;                             \
3125
   } while (0)
3126
3127
#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3128
                                arg7,arg8,arg9,arg10,arg11,arg12) \
3129
   do {                                                           \
3130
      volatile OrigFn        _orig = (orig);                      \
3131
      volatile unsigned long _argvec[3+12];                       \
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
      _argvec[2+4] = (unsigned long)arg4;                         \
3140
      _argvec[2+5] = (unsigned long)arg5;                         \
3141
      _argvec[2+6] = (unsigned long)arg6;                         \
3142
      _argvec[2+7] = (unsigned long)arg7;                         \
3143
      _argvec[2+8] = (unsigned long)arg8;                         \
3144
      _argvec[2+9] = (unsigned long)arg9;                         \
3145
      _argvec[2+10] = (unsigned long)arg10;                       \
3146
      _argvec[2+11] = (unsigned long)arg11;                       \
3147
      _argvec[2+12] = (unsigned long)arg12;                       \
3148
      __asm__ volatile(                                           \
3149
         VALGRIND_ALIGN_STACK                                     \
3150
         "mr 11,%1\n\t"                                           \
3151
         "std 2,-16(11)\n\t"  /* save tocptr */                   \
3152
         "ld   2,-8(11)\n\t"  /* use nraddr's tocptr */           \
3153
         "addi 1,1,-144\n\t"  /* expand stack frame */            \
3154
         /* arg12 */                                              \
3155
         "ld  3,96(11)\n\t"                                       \
3156
         "std 3,136(1)\n\t"                                       \
3157
         /* arg11 */                                              \
3158
         "ld  3,88(11)\n\t"                                       \
3159
         "std 3,128(1)\n\t"                                       \
3160
         /* arg10 */                                              \
3161
         "ld  3,80(11)\n\t"                                       \
3162
         "std 3,120(1)\n\t"                                       \
3163
         /* arg9 */                                               \
3164
         "ld  3,72(11)\n\t"                                       \
3165
         "std 3,112(1)\n\t"                                       \
3166
         /* args1-8 */                                            \
3167
         "ld   3, 8(11)\n\t"  /* arg1->r3 */                      \
3168
         "ld   4, 16(11)\n\t" /* arg2->r4 */                      \
3169
         "ld   5, 24(11)\n\t" /* arg3->r5 */                      \
3170
         "ld   6, 32(11)\n\t" /* arg4->r6 */                      \
3171
         "ld   7, 40(11)\n\t" /* arg5->r7 */                      \
3172
         "ld   8, 48(11)\n\t" /* arg6->r8 */                      \
3173
         "ld   9, 56(11)\n\t" /* arg7->r9 */                      \
3174
         "ld  10, 64(11)\n\t" /* arg8->r10 */                     \
3175
         "ld  11, 0(11)\n\t"  /* target->r11 */                   \
3176
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11                  \
3177
         "mr 11,%1\n\t"                                           \
3178
         "mr %0,3\n\t"                                            \
3179
         "ld 2,-16(11)\n\t" /* restore tocptr */                  \
3180
         VALGRIND_RESTORE_STACK                                   \
3181
         : /*out*/   "=r" (_res)                                  \
3182
         : /*in*/    "r" (&_argvec[2])                            \
3183
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3184
      );                                                          \
3185
      lval = (__typeof__(lval)) _res;                             \
3186
   } while (0)
3187
3188
#endif /* PLAT_ppc64be_linux */
3189
3190
/* ------------------------- ppc64le-linux ----------------------- */
3191
#if defined(PLAT_ppc64le_linux)
3192
3193
/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
3194
3195
/* These regs are trashed by the hidden call. */
3196
#define __CALLER_SAVED_REGS                                       \
3197
   "lr", "ctr", "xer",                                            \
3198
   "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",        \
3199
   "r0", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",         \
3200
   "r11", "r12", "r13"
3201
3202
/* Macros to save and align the stack before making a function
3203
   call and restore it afterwards as gcc may not keep the stack
3204
   pointer aligned if it doesn't realise calls are being made
3205
   to other functions. */
3206
3207
#define VALGRIND_ALIGN_STACK               \
3208
      "mr 28,1\n\t"                        \
3209
      "rldicr 1,1,0,59\n\t"
3210
#define VALGRIND_RESTORE_STACK             \
3211
      "mr 1,28\n\t"
3212
3213
/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
3214
   long) == 8. */
3215
3216
#define CALL_FN_W_v(lval, orig)                                   \
3217
   do {                                                           \
3218
      volatile OrigFn        _orig = (orig);                      \
3219
      volatile unsigned long _argvec[3+0];                        \
3220
      volatile unsigned long _res;                                \
3221
      /* _argvec[0] holds current r2 across the call */           \
3222
      _argvec[1] = (unsigned long)_orig.r2;                       \
3223
      _argvec[2] = (unsigned long)_orig.nraddr;                   \
3224
      __asm__ volatile(                                           \
3225
         VALGRIND_ALIGN_STACK                                     \
3226
         "mr 12,%1\n\t"                                           \
3227
         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3228
         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3229
         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3230
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3231
         "mr 12,%1\n\t"                                           \
3232
         "mr %0,3\n\t"                                            \
3233
         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3234
         VALGRIND_RESTORE_STACK                                   \
3235
         : /*out*/   "=r" (_res)                                  \
3236
         : /*in*/    "r" (&_argvec[2])                            \
3237
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3238
      );                                                          \
3239
      lval = (__typeof__(lval)) _res;                             \
3240
   } while (0)
3241
3242
#define CALL_FN_W_W(lval, orig, arg1)                             \
3243
   do {                                                           \
3244
      volatile OrigFn        _orig = (orig);                      \
3245
      volatile unsigned long _argvec[3+1];                        \
3246
      volatile unsigned long _res;                                \
3247
      /* _argvec[0] holds current r2 across the call */           \
3248
      _argvec[1]   = (unsigned long)_orig.r2;                     \
3249
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3250
      _argvec[2+1] = (unsigned long)arg1;                         \
3251
      __asm__ volatile(                                           \
3252
         VALGRIND_ALIGN_STACK                                     \
3253
         "mr 12,%1\n\t"                                           \
3254
         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3255
         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3256
         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3257
         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3258
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3259
         "mr 12,%1\n\t"                                           \
3260
         "mr %0,3\n\t"                                            \
3261
         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3262
         VALGRIND_RESTORE_STACK                                   \
3263
         : /*out*/   "=r" (_res)                                  \
3264
         : /*in*/    "r" (&_argvec[2])                            \
3265
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3266
      );                                                          \
3267
      lval = (__typeof__(lval)) _res;                             \
3268
   } while (0)
3269
3270
#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
3271
   do {                                                           \
3272
      volatile OrigFn        _orig = (orig);                      \
3273
      volatile unsigned long _argvec[3+2];                        \
3274
      volatile unsigned long _res;                                \
3275
      /* _argvec[0] holds current r2 across the call */           \
3276
      _argvec[1]   = (unsigned long)_orig.r2;                     \
3277
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3278
      _argvec[2+1] = (unsigned long)arg1;                         \
3279
      _argvec[2+2] = (unsigned long)arg2;                         \
3280
      __asm__ volatile(                                           \
3281
         VALGRIND_ALIGN_STACK                                     \
3282
         "mr 12,%1\n\t"                                           \
3283
         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3284
         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3285
         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3286
         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3287
         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3288
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3289
         "mr 12,%1\n\t"                                           \
3290
         "mr %0,3\n\t"                                            \
3291
         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3292
         VALGRIND_RESTORE_STACK                                   \
3293
         : /*out*/   "=r" (_res)                                  \
3294
         : /*in*/    "r" (&_argvec[2])                            \
3295
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3296
      );                                                          \
3297
      lval = (__typeof__(lval)) _res;                             \
3298
   } while (0)
3299
3300
#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
3301
   do {                                                           \
3302
      volatile OrigFn        _orig = (orig);                      \
3303
      volatile unsigned long _argvec[3+3];                        \
3304
      volatile unsigned long _res;                                \
3305
      /* _argvec[0] holds current r2 across the call */           \
3306
      _argvec[1]   = (unsigned long)_orig.r2;                     \
3307
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3308
      _argvec[2+1] = (unsigned long)arg1;                         \
3309
      _argvec[2+2] = (unsigned long)arg2;                         \
3310
      _argvec[2+3] = (unsigned long)arg3;                         \
3311
      __asm__ volatile(                                           \
3312
         VALGRIND_ALIGN_STACK                                     \
3313
         "mr 12,%1\n\t"                                           \
3314
         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3315
         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3316
         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3317
         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3318
         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3319
         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3320
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3321
         "mr 12,%1\n\t"                                           \
3322
         "mr %0,3\n\t"                                            \
3323
         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3324
         VALGRIND_RESTORE_STACK                                   \
3325
         : /*out*/   "=r" (_res)                                  \
3326
         : /*in*/    "r" (&_argvec[2])                            \
3327
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3328
      );                                                          \
3329
      lval = (__typeof__(lval)) _res;                             \
3330
   } while (0)
3331
3332
#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
3333
   do {                                                           \
3334
      volatile OrigFn        _orig = (orig);                      \
3335
      volatile unsigned long _argvec[3+4];                        \
3336
      volatile unsigned long _res;                                \
3337
      /* _argvec[0] holds current r2 across the call */           \
3338
      _argvec[1]   = (unsigned long)_orig.r2;                     \
3339
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3340
      _argvec[2+1] = (unsigned long)arg1;                         \
3341
      _argvec[2+2] = (unsigned long)arg2;                         \
3342
      _argvec[2+3] = (unsigned long)arg3;                         \
3343
      _argvec[2+4] = (unsigned long)arg4;                         \
3344
      __asm__ volatile(                                           \
3345
         VALGRIND_ALIGN_STACK                                     \
3346
         "mr 12,%1\n\t"                                           \
3347
         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3348
         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3349
         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3350
         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3351
         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3352
         "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3353
         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3354
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3355
         "mr 12,%1\n\t"                                           \
3356
         "mr %0,3\n\t"                                            \
3357
         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3358
         VALGRIND_RESTORE_STACK                                   \
3359
         : /*out*/   "=r" (_res)                                  \
3360
         : /*in*/    "r" (&_argvec[2])                            \
3361
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3362
      );                                                          \
3363
      lval = (__typeof__(lval)) _res;                             \
3364
   } while (0)
3365
3366
#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
3367
   do {                                                           \
3368
      volatile OrigFn        _orig = (orig);                      \
3369
      volatile unsigned long _argvec[3+5];                        \
3370
      volatile unsigned long _res;                                \
3371
      /* _argvec[0] holds current r2 across the call */           \
3372
      _argvec[1]   = (unsigned long)_orig.r2;                     \
3373
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3374
      _argvec[2+1] = (unsigned long)arg1;                         \
3375
      _argvec[2+2] = (unsigned long)arg2;                         \
3376
      _argvec[2+3] = (unsigned long)arg3;                         \
3377
      _argvec[2+4] = (unsigned long)arg4;                         \
3378
      _argvec[2+5] = (unsigned long)arg5;                         \
3379
      __asm__ volatile(                                           \
3380
         VALGRIND_ALIGN_STACK                                     \
3381
         "mr 12,%1\n\t"                                           \
3382
         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3383
         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3384
         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3385
         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3386
         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3387
         "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3388
         "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3389
         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3390
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3391
         "mr 12,%1\n\t"                                           \
3392
         "mr %0,3\n\t"                                            \
3393
         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3394
         VALGRIND_RESTORE_STACK                                   \
3395
         : /*out*/   "=r" (_res)                                  \
3396
         : /*in*/    "r" (&_argvec[2])                            \
3397
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3398
      );                                                          \
3399
      lval = (__typeof__(lval)) _res;                             \
3400
   } while (0)
3401
3402
#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
3403
   do {                                                           \
3404
      volatile OrigFn        _orig = (orig);                      \
3405
      volatile unsigned long _argvec[3+6];                        \
3406
      volatile unsigned long _res;                                \
3407
      /* _argvec[0] holds current r2 across the call */           \
3408
      _argvec[1]   = (unsigned long)_orig.r2;                     \
3409
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3410
      _argvec[2+1] = (unsigned long)arg1;                         \
3411
      _argvec[2+2] = (unsigned long)arg2;                         \
3412
      _argvec[2+3] = (unsigned long)arg3;                         \
3413
      _argvec[2+4] = (unsigned long)arg4;                         \
3414
      _argvec[2+5] = (unsigned long)arg5;                         \
3415
      _argvec[2+6] = (unsigned long)arg6;                         \
3416
      __asm__ volatile(                                           \
3417
         VALGRIND_ALIGN_STACK                                     \
3418
         "mr 12,%1\n\t"                                           \
3419
         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3420
         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3421
         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3422
         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3423
         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3424
         "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3425
         "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3426
         "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3427
         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3428
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3429
         "mr 12,%1\n\t"                                           \
3430
         "mr %0,3\n\t"                                            \
3431
         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3432
         VALGRIND_RESTORE_STACK                                   \
3433
         : /*out*/   "=r" (_res)                                  \
3434
         : /*in*/    "r" (&_argvec[2])                            \
3435
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3436
      );                                                          \
3437
      lval = (__typeof__(lval)) _res;                             \
3438
   } while (0)
3439
3440
#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3441
                                 arg7)                            \
3442
   do {                                                           \
3443
      volatile OrigFn        _orig = (orig);                      \
3444
      volatile unsigned long _argvec[3+7];                        \
3445
      volatile unsigned long _res;                                \
3446
      /* _argvec[0] holds current r2 across the call */           \
3447
      _argvec[1]   = (unsigned long)_orig.r2;                     \
3448
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3449
      _argvec[2+1] = (unsigned long)arg1;                         \
3450
      _argvec[2+2] = (unsigned long)arg2;                         \
3451
      _argvec[2+3] = (unsigned long)arg3;                         \
3452
      _argvec[2+4] = (unsigned long)arg4;                         \
3453
      _argvec[2+5] = (unsigned long)arg5;                         \
3454
      _argvec[2+6] = (unsigned long)arg6;                         \
3455
      _argvec[2+7] = (unsigned long)arg7;                         \
3456
      __asm__ volatile(                                           \
3457
         VALGRIND_ALIGN_STACK                                     \
3458
         "mr 12,%1\n\t"                                           \
3459
         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3460
         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3461
         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3462
         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3463
         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3464
         "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3465
         "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3466
         "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3467
         "ld   9, 56(12)\n\t" /* arg7->r9 */                      \
3468
         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3469
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3470
         "mr 12,%1\n\t"                                           \
3471
         "mr %0,3\n\t"                                            \
3472
         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3473
         VALGRIND_RESTORE_STACK                                   \
3474
         : /*out*/   "=r" (_res)                                  \
3475
         : /*in*/    "r" (&_argvec[2])                            \
3476
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3477
      );                                                          \
3478
      lval = (__typeof__(lval)) _res;                             \
3479
   } while (0)
3480
3481
#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3482
                                 arg7,arg8)                       \
3483
   do {                                                           \
3484
      volatile OrigFn        _orig = (orig);                      \
3485
      volatile unsigned long _argvec[3+8];                        \
3486
      volatile unsigned long _res;                                \
3487
      /* _argvec[0] holds current r2 across the call */           \
3488
      _argvec[1]   = (unsigned long)_orig.r2;                     \
3489
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3490
      _argvec[2+1] = (unsigned long)arg1;                         \
3491
      _argvec[2+2] = (unsigned long)arg2;                         \
3492
      _argvec[2+3] = (unsigned long)arg3;                         \
3493
      _argvec[2+4] = (unsigned long)arg4;                         \
3494
      _argvec[2+5] = (unsigned long)arg5;                         \
3495
      _argvec[2+6] = (unsigned long)arg6;                         \
3496
      _argvec[2+7] = (unsigned long)arg7;                         \
3497
      _argvec[2+8] = (unsigned long)arg8;                         \
3498
      __asm__ volatile(                                           \
3499
         VALGRIND_ALIGN_STACK                                     \
3500
         "mr 12,%1\n\t"                                           \
3501
         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3502
         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3503
         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3504
         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3505
         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3506
         "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3507
         "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3508
         "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3509
         "ld   9, 56(12)\n\t" /* arg7->r9 */                      \
3510
         "ld  10, 64(12)\n\t" /* arg8->r10 */                     \
3511
         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3512
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3513
         "mr 12,%1\n\t"                                           \
3514
         "mr %0,3\n\t"                                            \
3515
         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3516
         VALGRIND_RESTORE_STACK                                   \
3517
         : /*out*/   "=r" (_res)                                  \
3518
         : /*in*/    "r" (&_argvec[2])                            \
3519
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3520
      );                                                          \
3521
      lval = (__typeof__(lval)) _res;                             \
3522
   } while (0)
3523
3524
#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3525
                                 arg7,arg8,arg9)                  \
3526
   do {                                                           \
3527
      volatile OrigFn        _orig = (orig);                      \
3528
      volatile unsigned long _argvec[3+9];                        \
3529
      volatile unsigned long _res;                                \
3530
      /* _argvec[0] holds current r2 across the call */           \
3531
      _argvec[1]   = (unsigned long)_orig.r2;                     \
3532
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3533
      _argvec[2+1] = (unsigned long)arg1;                         \
3534
      _argvec[2+2] = (unsigned long)arg2;                         \
3535
      _argvec[2+3] = (unsigned long)arg3;                         \
3536
      _argvec[2+4] = (unsigned long)arg4;                         \
3537
      _argvec[2+5] = (unsigned long)arg5;                         \
3538
      _argvec[2+6] = (unsigned long)arg6;                         \
3539
      _argvec[2+7] = (unsigned long)arg7;                         \
3540
      _argvec[2+8] = (unsigned long)arg8;                         \
3541
      _argvec[2+9] = (unsigned long)arg9;                         \
3542
      __asm__ volatile(                                           \
3543
         VALGRIND_ALIGN_STACK                                     \
3544
         "mr 12,%1\n\t"                                           \
3545
         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3546
         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3547
         "addi 1,1,-128\n\t"  /* expand stack frame */            \
3548
         /* arg9 */                                               \
3549
         "ld  3,72(12)\n\t"                                       \
3550
         "std 3,96(1)\n\t"                                        \
3551
         /* args1-8 */                                            \
3552
         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3553
         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3554
         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3555
         "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3556
         "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3557
         "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3558
         "ld   9, 56(12)\n\t" /* arg7->r9 */                      \
3559
         "ld  10, 64(12)\n\t" /* arg8->r10 */                     \
3560
         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3561
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3562
         "mr 12,%1\n\t"                                           \
3563
         "mr %0,3\n\t"                                            \
3564
         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3565
         VALGRIND_RESTORE_STACK                                   \
3566
         : /*out*/   "=r" (_res)                                  \
3567
         : /*in*/    "r" (&_argvec[2])                            \
3568
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3569
      );                                                          \
3570
      lval = (__typeof__(lval)) _res;                             \
3571
   } while (0)
3572
3573
#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3574
                                  arg7,arg8,arg9,arg10)           \
3575
   do {                                                           \
3576
      volatile OrigFn        _orig = (orig);                      \
3577
      volatile unsigned long _argvec[3+10];                       \
3578
      volatile unsigned long _res;                                \
3579
      /* _argvec[0] holds current r2 across the call */           \
3580
      _argvec[1]   = (unsigned long)_orig.r2;                     \
3581
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3582
      _argvec[2+1] = (unsigned long)arg1;                         \
3583
      _argvec[2+2] = (unsigned long)arg2;                         \
3584
      _argvec[2+3] = (unsigned long)arg3;                         \
3585
      _argvec[2+4] = (unsigned long)arg4;                         \
3586
      _argvec[2+5] = (unsigned long)arg5;                         \
3587
      _argvec[2+6] = (unsigned long)arg6;                         \
3588
      _argvec[2+7] = (unsigned long)arg7;                         \
3589
      _argvec[2+8] = (unsigned long)arg8;                         \
3590
      _argvec[2+9] = (unsigned long)arg9;                         \
3591
      _argvec[2+10] = (unsigned long)arg10;                       \
3592
      __asm__ volatile(                                           \
3593
         VALGRIND_ALIGN_STACK                                     \
3594
         "mr 12,%1\n\t"                                           \
3595
         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3596
         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3597
         "addi 1,1,-128\n\t"  /* expand stack frame */            \
3598
         /* arg10 */                                              \
3599
         "ld  3,80(12)\n\t"                                       \
3600
         "std 3,104(1)\n\t"                                       \
3601
         /* arg9 */                                               \
3602
         "ld  3,72(12)\n\t"                                       \
3603
         "std 3,96(1)\n\t"                                        \
3604
         /* args1-8 */                                            \
3605
         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3606
         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3607
         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3608
         "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3609
         "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3610
         "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3611
         "ld   9, 56(12)\n\t" /* arg7->r9 */                      \
3612
         "ld  10, 64(12)\n\t" /* arg8->r10 */                     \
3613
         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3614
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3615
         "mr 12,%1\n\t"                                           \
3616
         "mr %0,3\n\t"                                            \
3617
         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3618
         VALGRIND_RESTORE_STACK                                   \
3619
         : /*out*/   "=r" (_res)                                  \
3620
         : /*in*/    "r" (&_argvec[2])                            \
3621
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3622
      );                                                          \
3623
      lval = (__typeof__(lval)) _res;                             \
3624
   } while (0)
3625
3626
#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3627
                                  arg7,arg8,arg9,arg10,arg11)     \
3628
   do {                                                           \
3629
      volatile OrigFn        _orig = (orig);                      \
3630
      volatile unsigned long _argvec[3+11];                       \
3631
      volatile unsigned long _res;                                \
3632
      /* _argvec[0] holds current r2 across the call */           \
3633
      _argvec[1]   = (unsigned long)_orig.r2;                     \
3634
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3635
      _argvec[2+1] = (unsigned long)arg1;                         \
3636
      _argvec[2+2] = (unsigned long)arg2;                         \
3637
      _argvec[2+3] = (unsigned long)arg3;                         \
3638
      _argvec[2+4] = (unsigned long)arg4;                         \
3639
      _argvec[2+5] = (unsigned long)arg5;                         \
3640
      _argvec[2+6] = (unsigned long)arg6;                         \
3641
      _argvec[2+7] = (unsigned long)arg7;                         \
3642
      _argvec[2+8] = (unsigned long)arg8;                         \
3643
      _argvec[2+9] = (unsigned long)arg9;                         \
3644
      _argvec[2+10] = (unsigned long)arg10;                       \
3645
      _argvec[2+11] = (unsigned long)arg11;                       \
3646
      __asm__ volatile(                                           \
3647
         VALGRIND_ALIGN_STACK                                     \
3648
         "mr 12,%1\n\t"                                           \
3649
         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3650
         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3651
         "addi 1,1,-144\n\t"  /* expand stack frame */            \
3652
         /* arg11 */                                              \
3653
         "ld  3,88(12)\n\t"                                       \
3654
         "std 3,112(1)\n\t"                                       \
3655
         /* arg10 */                                              \
3656
         "ld  3,80(12)\n\t"                                       \
3657
         "std 3,104(1)\n\t"                                       \
3658
         /* arg9 */                                               \
3659
         "ld  3,72(12)\n\t"                                       \
3660
         "std 3,96(1)\n\t"                                        \
3661
         /* args1-8 */                                            \
3662
         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3663
         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3664
         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3665
         "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3666
         "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3667
         "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3668
         "ld   9, 56(12)\n\t" /* arg7->r9 */                      \
3669
         "ld  10, 64(12)\n\t" /* arg8->r10 */                     \
3670
         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3671
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3672
         "mr 12,%1\n\t"                                           \
3673
         "mr %0,3\n\t"                                            \
3674
         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3675
         VALGRIND_RESTORE_STACK                                   \
3676
         : /*out*/   "=r" (_res)                                  \
3677
         : /*in*/    "r" (&_argvec[2])                            \
3678
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3679
      );                                                          \
3680
      lval = (__typeof__(lval)) _res;                             \
3681
   } while (0)
3682
3683
#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
3684
                                arg7,arg8,arg9,arg10,arg11,arg12) \
3685
   do {                                                           \
3686
      volatile OrigFn        _orig = (orig);                      \
3687
      volatile unsigned long _argvec[3+12];                       \
3688
      volatile unsigned long _res;                                \
3689
      /* _argvec[0] holds current r2 across the call */           \
3690
      _argvec[1]   = (unsigned long)_orig.r2;                     \
3691
      _argvec[2]   = (unsigned long)_orig.nraddr;                 \
3692
      _argvec[2+1] = (unsigned long)arg1;                         \
3693
      _argvec[2+2] = (unsigned long)arg2;                         \
3694
      _argvec[2+3] = (unsigned long)arg3;                         \
3695
      _argvec[2+4] = (unsigned long)arg4;                         \
3696
      _argvec[2+5] = (unsigned long)arg5;                         \
3697
      _argvec[2+6] = (unsigned long)arg6;                         \
3698
      _argvec[2+7] = (unsigned long)arg7;                         \
3699
      _argvec[2+8] = (unsigned long)arg8;                         \
3700
      _argvec[2+9] = (unsigned long)arg9;                         \
3701
      _argvec[2+10] = (unsigned long)arg10;                       \
3702
      _argvec[2+11] = (unsigned long)arg11;                       \
3703
      _argvec[2+12] = (unsigned long)arg12;                       \
3704
      __asm__ volatile(                                           \
3705
         VALGRIND_ALIGN_STACK                                     \
3706
         "mr 12,%1\n\t"                                           \
3707
         "std 2,-16(12)\n\t"  /* save tocptr */                   \
3708
         "ld   2,-8(12)\n\t"  /* use nraddr's tocptr */           \
3709
         "addi 1,1,-144\n\t"  /* expand stack frame */            \
3710
         /* arg12 */                                              \
3711
         "ld  3,96(12)\n\t"                                       \
3712
         "std 3,120(1)\n\t"                                       \
3713
         /* arg11 */                                              \
3714
         "ld  3,88(12)\n\t"                                       \
3715
         "std 3,112(1)\n\t"                                       \
3716
         /* arg10 */                                              \
3717
         "ld  3,80(12)\n\t"                                       \
3718
         "std 3,104(1)\n\t"                                       \
3719
         /* arg9 */                                               \
3720
         "ld  3,72(12)\n\t"                                       \
3721
         "std 3,96(1)\n\t"                                        \
3722
         /* args1-8 */                                            \
3723
         "ld   3, 8(12)\n\t"  /* arg1->r3 */                      \
3724
         "ld   4, 16(12)\n\t" /* arg2->r4 */                      \
3725
         "ld   5, 24(12)\n\t" /* arg3->r5 */                      \
3726
         "ld   6, 32(12)\n\t" /* arg4->r6 */                      \
3727
         "ld   7, 40(12)\n\t" /* arg5->r7 */                      \
3728
         "ld   8, 48(12)\n\t" /* arg6->r8 */                      \
3729
         "ld   9, 56(12)\n\t" /* arg7->r9 */                      \
3730
         "ld  10, 64(12)\n\t" /* arg8->r10 */                     \
3731
         "ld  12, 0(12)\n\t"  /* target->r12 */                   \
3732
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12                  \
3733
         "mr 12,%1\n\t"                                           \
3734
         "mr %0,3\n\t"                                            \
3735
         "ld 2,-16(12)\n\t" /* restore tocptr */                  \
3736
         VALGRIND_RESTORE_STACK                                   \
3737
         : /*out*/   "=r" (_res)                                  \
3738
         : /*in*/    "r" (&_argvec[2])                            \
3739
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28"   \
3740
      );                                                          \
3741
      lval = (__typeof__(lval)) _res;                             \
3742
   } while (0)
3743
3744
#endif /* PLAT_ppc64le_linux */
3745
3746
/* ------------------------- arm-linux ------------------------- */
3747
3748
#if defined(PLAT_arm_linux)
3749
3750
/* These regs are trashed by the hidden call. */
3751
#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4", "r12", "r14"
3752
3753
/* Macros to save and align the stack before making a function
3754
   call and restore it afterwards as gcc may not keep the stack
3755
   pointer aligned if it doesn't realise calls are being made
3756
   to other functions. */
3757
3758
/* This is a bit tricky.  We store the original stack pointer in r10
3759
   as it is callee-saves.  gcc doesn't allow the use of r11 for some
3760
   reason.  Also, we can't directly "bic" the stack pointer in thumb
3761
   mode since r13 isn't an allowed register number in that context.
3762
   So use r4 as a temporary, since that is about to get trashed
3763
   anyway, just after each use of this macro.  Side effect is we need
3764
   to be very careful about any future changes, since
3765
   VALGRIND_ALIGN_STACK simply assumes r4 is usable. */
3766
#define VALGRIND_ALIGN_STACK               \
3767
      "mov r10, sp\n\t"                    \
3768
      "mov r4,  sp\n\t"                    \
3769
      "bic r4,  r4, #7\n\t"                \
3770
      "mov sp,  r4\n\t"
3771
#define VALGRIND_RESTORE_STACK             \
3772
      "mov sp,  r10\n\t"
3773
3774
/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
3775
   long) == 4. */
3776
3777
#define CALL_FN_W_v(lval, orig)                                   \
3778
   do {                                                           \
3779
      volatile OrigFn        _orig = (orig);                      \
3780
      volatile unsigned long _argvec[1];                          \
3781
      volatile unsigned long _res;                                \
3782
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
3783
      __asm__ volatile(                                           \
3784
         VALGRIND_ALIGN_STACK                                     \
3785
         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3786
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3787
         VALGRIND_RESTORE_STACK                                   \
3788
         "mov %0, r0\n"                                           \
3789
         : /*out*/   "=r" (_res)                                  \
3790
         : /*in*/    "0" (&_argvec[0])                            \
3791
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3792
      );                                                          \
3793
      lval = (__typeof__(lval)) _res;                             \
3794
   } while (0)
3795
3796
#define CALL_FN_W_W(lval, orig, arg1)                             \
3797
   do {                                                           \
3798
      volatile OrigFn        _orig = (orig);                      \
3799
      volatile unsigned long _argvec[2];                          \
3800
      volatile unsigned long _res;                                \
3801
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
3802
      _argvec[1] = (unsigned long)(arg1);                         \
3803
      __asm__ volatile(                                           \
3804
         VALGRIND_ALIGN_STACK                                     \
3805
         "ldr r0, [%1, #4] \n\t"                                  \
3806
         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3807
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3808
         VALGRIND_RESTORE_STACK                                   \
3809
         "mov %0, r0\n"                                           \
3810
         : /*out*/   "=r" (_res)                                  \
3811
         : /*in*/    "0" (&_argvec[0])                            \
3812
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3813
      );                                                          \
3814
      lval = (__typeof__(lval)) _res;                             \
3815
   } while (0)
3816
3817
#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
3818
   do {                                                           \
3819
      volatile OrigFn        _orig = (orig);                      \
3820
      volatile unsigned long _argvec[3];                          \
3821
      volatile unsigned long _res;                                \
3822
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
3823
      _argvec[1] = (unsigned long)(arg1);                         \
3824
      _argvec[2] = (unsigned long)(arg2);                         \
3825
      __asm__ volatile(                                           \
3826
         VALGRIND_ALIGN_STACK                                     \
3827
         "ldr r0, [%1, #4] \n\t"                                  \
3828
         "ldr r1, [%1, #8] \n\t"                                  \
3829
         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3830
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3831
         VALGRIND_RESTORE_STACK                                   \
3832
         "mov %0, r0\n"                                           \
3833
         : /*out*/   "=r" (_res)                                  \
3834
         : /*in*/    "0" (&_argvec[0])                            \
3835
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3836
      );                                                          \
3837
      lval = (__typeof__(lval)) _res;                             \
3838
   } while (0)
3839
3840
#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
3841
   do {                                                           \
3842
      volatile OrigFn        _orig = (orig);                      \
3843
      volatile unsigned long _argvec[4];                          \
3844
      volatile unsigned long _res;                                \
3845
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
3846
      _argvec[1] = (unsigned long)(arg1);                         \
3847
      _argvec[2] = (unsigned long)(arg2);                         \
3848
      _argvec[3] = (unsigned long)(arg3);                         \
3849
      __asm__ volatile(                                           \
3850
         VALGRIND_ALIGN_STACK                                     \
3851
         "ldr r0, [%1, #4] \n\t"                                  \
3852
         "ldr r1, [%1, #8] \n\t"                                  \
3853
         "ldr r2, [%1, #12] \n\t"                                 \
3854
         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3855
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3856
         VALGRIND_RESTORE_STACK                                   \
3857
         "mov %0, r0\n"                                           \
3858
         : /*out*/   "=r" (_res)                                  \
3859
         : /*in*/    "0" (&_argvec[0])                            \
3860
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3861
      );                                                          \
3862
      lval = (__typeof__(lval)) _res;                             \
3863
   } while (0)
3864
3865
#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
3866
   do {                                                           \
3867
      volatile OrigFn        _orig = (orig);                      \
3868
      volatile unsigned long _argvec[5];                          \
3869
      volatile unsigned long _res;                                \
3870
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
3871
      _argvec[1] = (unsigned long)(arg1);                         \
3872
      _argvec[2] = (unsigned long)(arg2);                         \
3873
      _argvec[3] = (unsigned long)(arg3);                         \
3874
      _argvec[4] = (unsigned long)(arg4);                         \
3875
      __asm__ volatile(                                           \
3876
         VALGRIND_ALIGN_STACK                                     \
3877
         "ldr r0, [%1, #4] \n\t"                                  \
3878
         "ldr r1, [%1, #8] \n\t"                                  \
3879
         "ldr r2, [%1, #12] \n\t"                                 \
3880
         "ldr r3, [%1, #16] \n\t"                                 \
3881
         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3882
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3883
         VALGRIND_RESTORE_STACK                                   \
3884
         "mov %0, r0"                                             \
3885
         : /*out*/   "=r" (_res)                                  \
3886
         : /*in*/    "0" (&_argvec[0])                            \
3887
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3888
      );                                                          \
3889
      lval = (__typeof__(lval)) _res;                             \
3890
   } while (0)
3891
3892
#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
3893
   do {                                                           \
3894
      volatile OrigFn        _orig = (orig);                      \
3895
      volatile unsigned long _argvec[6];                          \
3896
      volatile unsigned long _res;                                \
3897
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
3898
      _argvec[1] = (unsigned long)(arg1);                         \
3899
      _argvec[2] = (unsigned long)(arg2);                         \
3900
      _argvec[3] = (unsigned long)(arg3);                         \
3901
      _argvec[4] = (unsigned long)(arg4);                         \
3902
      _argvec[5] = (unsigned long)(arg5);                         \
3903
      __asm__ volatile(                                           \
3904
         VALGRIND_ALIGN_STACK                                     \
3905
         "sub sp, sp, #4 \n\t"                                    \
3906
         "ldr r0, [%1, #20] \n\t"                                 \
3907
         "push {r0} \n\t"                                         \
3908
         "ldr r0, [%1, #4] \n\t"                                  \
3909
         "ldr r1, [%1, #8] \n\t"                                  \
3910
         "ldr r2, [%1, #12] \n\t"                                 \
3911
         "ldr r3, [%1, #16] \n\t"                                 \
3912
         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3913
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3914
         VALGRIND_RESTORE_STACK                                   \
3915
         "mov %0, r0"                                             \
3916
         : /*out*/   "=r" (_res)                                  \
3917
         : /*in*/    "0" (&_argvec[0])                            \
3918
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3919
      );                                                          \
3920
      lval = (__typeof__(lval)) _res;                             \
3921
   } while (0)
3922
3923
#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
3924
   do {                                                           \
3925
      volatile OrigFn        _orig = (orig);                      \
3926
      volatile unsigned long _argvec[7];                          \
3927
      volatile unsigned long _res;                                \
3928
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
3929
      _argvec[1] = (unsigned long)(arg1);                         \
3930
      _argvec[2] = (unsigned long)(arg2);                         \
3931
      _argvec[3] = (unsigned long)(arg3);                         \
3932
      _argvec[4] = (unsigned long)(arg4);                         \
3933
      _argvec[5] = (unsigned long)(arg5);                         \
3934
      _argvec[6] = (unsigned long)(arg6);                         \
3935
      __asm__ volatile(                                           \
3936
         VALGRIND_ALIGN_STACK                                     \
3937
         "ldr r0, [%1, #20] \n\t"                                 \
3938
         "ldr r1, [%1, #24] \n\t"                                 \
3939
         "push {r0, r1} \n\t"                                     \
3940
         "ldr r0, [%1, #4] \n\t"                                  \
3941
         "ldr r1, [%1, #8] \n\t"                                  \
3942
         "ldr r2, [%1, #12] \n\t"                                 \
3943
         "ldr r3, [%1, #16] \n\t"                                 \
3944
         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3945
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3946
         VALGRIND_RESTORE_STACK                                   \
3947
         "mov %0, r0"                                             \
3948
         : /*out*/   "=r" (_res)                                  \
3949
         : /*in*/    "0" (&_argvec[0])                            \
3950
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3951
      );                                                          \
3952
      lval = (__typeof__(lval)) _res;                             \
3953
   } while (0)
3954
3955
#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3956
                                 arg7)                            \
3957
   do {                                                           \
3958
      volatile OrigFn        _orig = (orig);                      \
3959
      volatile unsigned long _argvec[8];                          \
3960
      volatile unsigned long _res;                                \
3961
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
3962
      _argvec[1] = (unsigned long)(arg1);                         \
3963
      _argvec[2] = (unsigned long)(arg2);                         \
3964
      _argvec[3] = (unsigned long)(arg3);                         \
3965
      _argvec[4] = (unsigned long)(arg4);                         \
3966
      _argvec[5] = (unsigned long)(arg5);                         \
3967
      _argvec[6] = (unsigned long)(arg6);                         \
3968
      _argvec[7] = (unsigned long)(arg7);                         \
3969
      __asm__ volatile(                                           \
3970
         VALGRIND_ALIGN_STACK                                     \
3971
         "sub sp, sp, #4 \n\t"                                    \
3972
         "ldr r0, [%1, #20] \n\t"                                 \
3973
         "ldr r1, [%1, #24] \n\t"                                 \
3974
         "ldr r2, [%1, #28] \n\t"                                 \
3975
         "push {r0, r1, r2} \n\t"                                 \
3976
         "ldr r0, [%1, #4] \n\t"                                  \
3977
         "ldr r1, [%1, #8] \n\t"                                  \
3978
         "ldr r2, [%1, #12] \n\t"                                 \
3979
         "ldr r3, [%1, #16] \n\t"                                 \
3980
         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
3981
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
3982
         VALGRIND_RESTORE_STACK                                   \
3983
         "mov %0, r0"                                             \
3984
         : /*out*/   "=r" (_res)                                  \
3985
         : /*in*/    "0" (&_argvec[0])                            \
3986
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
3987
      );                                                          \
3988
      lval = (__typeof__(lval)) _res;                             \
3989
   } while (0)
3990
3991
#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
3992
                                 arg7,arg8)                       \
3993
   do {                                                           \
3994
      volatile OrigFn        _orig = (orig);                      \
3995
      volatile unsigned long _argvec[9];                          \
3996
      volatile unsigned long _res;                                \
3997
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
3998
      _argvec[1] = (unsigned long)(arg1);                         \
3999
      _argvec[2] = (unsigned long)(arg2);                         \
4000
      _argvec[3] = (unsigned long)(arg3);                         \
4001
      _argvec[4] = (unsigned long)(arg4);                         \
4002
      _argvec[5] = (unsigned long)(arg5);                         \
4003
      _argvec[6] = (unsigned long)(arg6);                         \
4004
      _argvec[7] = (unsigned long)(arg7);                         \
4005
      _argvec[8] = (unsigned long)(arg8);                         \
4006
      __asm__ volatile(                                           \
4007
         VALGRIND_ALIGN_STACK                                     \
4008
         "ldr r0, [%1, #20] \n\t"                                 \
4009
         "ldr r1, [%1, #24] \n\t"                                 \
4010
         "ldr r2, [%1, #28] \n\t"                                 \
4011
         "ldr r3, [%1, #32] \n\t"                                 \
4012
         "push {r0, r1, r2, r3} \n\t"                             \
4013
         "ldr r0, [%1, #4] \n\t"                                  \
4014
         "ldr r1, [%1, #8] \n\t"                                  \
4015
         "ldr r2, [%1, #12] \n\t"                                 \
4016
         "ldr r3, [%1, #16] \n\t"                                 \
4017
         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
4018
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
4019
         VALGRIND_RESTORE_STACK                                   \
4020
         "mov %0, r0"                                             \
4021
         : /*out*/   "=r" (_res)                                  \
4022
         : /*in*/    "0" (&_argvec[0])                            \
4023
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
4024
      );                                                          \
4025
      lval = (__typeof__(lval)) _res;                             \
4026
   } while (0)
4027
4028
#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
4029
                                 arg7,arg8,arg9)                  \
4030
   do {                                                           \
4031
      volatile OrigFn        _orig = (orig);                      \
4032
      volatile unsigned long _argvec[10];                         \
4033
      volatile unsigned long _res;                                \
4034
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4035
      _argvec[1] = (unsigned long)(arg1);                         \
4036
      _argvec[2] = (unsigned long)(arg2);                         \
4037
      _argvec[3] = (unsigned long)(arg3);                         \
4038
      _argvec[4] = (unsigned long)(arg4);                         \
4039
      _argvec[5] = (unsigned long)(arg5);                         \
4040
      _argvec[6] = (unsigned long)(arg6);                         \
4041
      _argvec[7] = (unsigned long)(arg7);                         \
4042
      _argvec[8] = (unsigned long)(arg8);                         \
4043
      _argvec[9] = (unsigned long)(arg9);                         \
4044
      __asm__ volatile(                                           \
4045
         VALGRIND_ALIGN_STACK                                     \
4046
         "sub sp, sp, #4 \n\t"                                    \
4047
         "ldr r0, [%1, #20] \n\t"                                 \
4048
         "ldr r1, [%1, #24] \n\t"                                 \
4049
         "ldr r2, [%1, #28] \n\t"                                 \
4050
         "ldr r3, [%1, #32] \n\t"                                 \
4051
         "ldr r4, [%1, #36] \n\t"                                 \
4052
         "push {r0, r1, r2, r3, r4} \n\t"                         \
4053
         "ldr r0, [%1, #4] \n\t"                                  \
4054
         "ldr r1, [%1, #8] \n\t"                                  \
4055
         "ldr r2, [%1, #12] \n\t"                                 \
4056
         "ldr r3, [%1, #16] \n\t"                                 \
4057
         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
4058
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
4059
         VALGRIND_RESTORE_STACK                                   \
4060
         "mov %0, r0"                                             \
4061
         : /*out*/   "=r" (_res)                                  \
4062
         : /*in*/    "0" (&_argvec[0])                            \
4063
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
4064
      );                                                          \
4065
      lval = (__typeof__(lval)) _res;                             \
4066
   } while (0)
4067
4068
#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
4069
                                  arg7,arg8,arg9,arg10)           \
4070
   do {                                                           \
4071
      volatile OrigFn        _orig = (orig);                      \
4072
      volatile unsigned long _argvec[11];                         \
4073
      volatile unsigned long _res;                                \
4074
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4075
      _argvec[1] = (unsigned long)(arg1);                         \
4076
      _argvec[2] = (unsigned long)(arg2);                         \
4077
      _argvec[3] = (unsigned long)(arg3);                         \
4078
      _argvec[4] = (unsigned long)(arg4);                         \
4079
      _argvec[5] = (unsigned long)(arg5);                         \
4080
      _argvec[6] = (unsigned long)(arg6);                         \
4081
      _argvec[7] = (unsigned long)(arg7);                         \
4082
      _argvec[8] = (unsigned long)(arg8);                         \
4083
      _argvec[9] = (unsigned long)(arg9);                         \
4084
      _argvec[10] = (unsigned long)(arg10);                       \
4085
      __asm__ volatile(                                           \
4086
         VALGRIND_ALIGN_STACK                                     \
4087
         "ldr r0, [%1, #40] \n\t"                                 \
4088
         "push {r0} \n\t"                                         \
4089
         "ldr r0, [%1, #20] \n\t"                                 \
4090
         "ldr r1, [%1, #24] \n\t"                                 \
4091
         "ldr r2, [%1, #28] \n\t"                                 \
4092
         "ldr r3, [%1, #32] \n\t"                                 \
4093
         "ldr r4, [%1, #36] \n\t"                                 \
4094
         "push {r0, r1, r2, r3, r4} \n\t"                         \
4095
         "ldr r0, [%1, #4] \n\t"                                  \
4096
         "ldr r1, [%1, #8] \n\t"                                  \
4097
         "ldr r2, [%1, #12] \n\t"                                 \
4098
         "ldr r3, [%1, #16] \n\t"                                 \
4099
         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
4100
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
4101
         VALGRIND_RESTORE_STACK                                   \
4102
         "mov %0, r0"                                             \
4103
         : /*out*/   "=r" (_res)                                  \
4104
         : /*in*/    "0" (&_argvec[0])                            \
4105
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
4106
      );                                                          \
4107
      lval = (__typeof__(lval)) _res;                             \
4108
   } while (0)
4109
4110
#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
4111
                                  arg6,arg7,arg8,arg9,arg10,      \
4112
                                  arg11)                          \
4113
   do {                                                           \
4114
      volatile OrigFn        _orig = (orig);                      \
4115
      volatile unsigned long _argvec[12];                         \
4116
      volatile unsigned long _res;                                \
4117
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4118
      _argvec[1] = (unsigned long)(arg1);                         \
4119
      _argvec[2] = (unsigned long)(arg2);                         \
4120
      _argvec[3] = (unsigned long)(arg3);                         \
4121
      _argvec[4] = (unsigned long)(arg4);                         \
4122
      _argvec[5] = (unsigned long)(arg5);                         \
4123
      _argvec[6] = (unsigned long)(arg6);                         \
4124
      _argvec[7] = (unsigned long)(arg7);                         \
4125
      _argvec[8] = (unsigned long)(arg8);                         \
4126
      _argvec[9] = (unsigned long)(arg9);                         \
4127
      _argvec[10] = (unsigned long)(arg10);                       \
4128
      _argvec[11] = (unsigned long)(arg11);                       \
4129
      __asm__ volatile(                                           \
4130
         VALGRIND_ALIGN_STACK                                     \
4131
         "sub sp, sp, #4 \n\t"                                    \
4132
         "ldr r0, [%1, #40] \n\t"                                 \
4133
         "ldr r1, [%1, #44] \n\t"                                 \
4134
         "push {r0, r1} \n\t"                                     \
4135
         "ldr r0, [%1, #20] \n\t"                                 \
4136
         "ldr r1, [%1, #24] \n\t"                                 \
4137
         "ldr r2, [%1, #28] \n\t"                                 \
4138
         "ldr r3, [%1, #32] \n\t"                                 \
4139
         "ldr r4, [%1, #36] \n\t"                                 \
4140
         "push {r0, r1, r2, r3, r4} \n\t"                         \
4141
         "ldr r0, [%1, #4] \n\t"                                  \
4142
         "ldr r1, [%1, #8] \n\t"                                  \
4143
         "ldr r2, [%1, #12] \n\t"                                 \
4144
         "ldr r3, [%1, #16] \n\t"                                 \
4145
         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
4146
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
4147
         VALGRIND_RESTORE_STACK                                   \
4148
         "mov %0, r0"                                             \
4149
         : /*out*/   "=r" (_res)                                  \
4150
         : /*in*/    "0" (&_argvec[0])                            \
4151
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
4152
      );                                                          \
4153
      lval = (__typeof__(lval)) _res;                             \
4154
   } while (0)
4155
4156
#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
4157
                                  arg6,arg7,arg8,arg9,arg10,      \
4158
                                  arg11,arg12)                    \
4159
   do {                                                           \
4160
      volatile OrigFn        _orig = (orig);                      \
4161
      volatile unsigned long _argvec[13];                         \
4162
      volatile unsigned long _res;                                \
4163
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4164
      _argvec[1] = (unsigned long)(arg1);                         \
4165
      _argvec[2] = (unsigned long)(arg2);                         \
4166
      _argvec[3] = (unsigned long)(arg3);                         \
4167
      _argvec[4] = (unsigned long)(arg4);                         \
4168
      _argvec[5] = (unsigned long)(arg5);                         \
4169
      _argvec[6] = (unsigned long)(arg6);                         \
4170
      _argvec[7] = (unsigned long)(arg7);                         \
4171
      _argvec[8] = (unsigned long)(arg8);                         \
4172
      _argvec[9] = (unsigned long)(arg9);                         \
4173
      _argvec[10] = (unsigned long)(arg10);                       \
4174
      _argvec[11] = (unsigned long)(arg11);                       \
4175
      _argvec[12] = (unsigned long)(arg12);                       \
4176
      __asm__ volatile(                                           \
4177
         VALGRIND_ALIGN_STACK                                     \
4178
         "ldr r0, [%1, #40] \n\t"                                 \
4179
         "ldr r1, [%1, #44] \n\t"                                 \
4180
         "ldr r2, [%1, #48] \n\t"                                 \
4181
         "push {r0, r1, r2} \n\t"                                 \
4182
         "ldr r0, [%1, #20] \n\t"                                 \
4183
         "ldr r1, [%1, #24] \n\t"                                 \
4184
         "ldr r2, [%1, #28] \n\t"                                 \
4185
         "ldr r3, [%1, #32] \n\t"                                 \
4186
         "ldr r4, [%1, #36] \n\t"                                 \
4187
         "push {r0, r1, r2, r3, r4} \n\t"                         \
4188
         "ldr r0, [%1, #4] \n\t"                                  \
4189
         "ldr r1, [%1, #8] \n\t"                                  \
4190
         "ldr r2, [%1, #12] \n\t"                                 \
4191
         "ldr r3, [%1, #16] \n\t"                                 \
4192
         "ldr r4, [%1] \n\t"  /* target->r4 */                    \
4193
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4                   \
4194
         VALGRIND_RESTORE_STACK                                   \
4195
         "mov %0, r0"                                             \
4196
         : /*out*/   "=r" (_res)                                  \
4197
         : /*in*/    "0" (&_argvec[0])                            \
4198
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10"   \
4199
      );                                                          \
4200
      lval = (__typeof__(lval)) _res;                             \
4201
   } while (0)
4202
4203
#endif /* PLAT_arm_linux */
4204
4205
/* ------------------------ arm64-linux ------------------------ */
4206
4207
#if defined(PLAT_arm64_linux)
4208
4209
/* These regs are trashed by the hidden call. */
4210
#define __CALLER_SAVED_REGS \
4211
     "x0", "x1", "x2", "x3","x4", "x5", "x6", "x7", "x8", "x9",   \
4212
     "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17",      \
4213
     "x18", "x19", "x20", "x30",                                  \
4214
     "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",  \
4215
     "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17",      \
4216
     "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25",      \
4217
     "v26", "v27", "v28", "v29", "v30", "v31"
4218
4219
/* x21 is callee-saved, so we can use it to save and restore SP around
4220
   the hidden call. */
4221
#define VALGRIND_ALIGN_STACK               \
4222
      "mov x21, sp\n\t"                    \
4223
      "bic sp, x21, #15\n\t"
4224
#define VALGRIND_RESTORE_STACK             \
4225
      "mov sp,  x21\n\t"
4226
4227
/* These CALL_FN_ macros assume that on arm64-linux,
4228
   sizeof(unsigned long) == 8. */
4229
4230
#define CALL_FN_W_v(lval, orig)                                   \
4231
   do {                                                           \
4232
      volatile OrigFn        _orig = (orig);                      \
4233
      volatile unsigned long _argvec[1];                          \
4234
      volatile unsigned long _res;                                \
4235
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4236
      __asm__ volatile(                                           \
4237
         VALGRIND_ALIGN_STACK                                     \
4238
         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4239
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4240
         VALGRIND_RESTORE_STACK                                   \
4241
         "mov %0, x0\n"                                           \
4242
         : /*out*/   "=r" (_res)                                  \
4243
         : /*in*/    "0" (&_argvec[0])                            \
4244
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4245
      );                                                          \
4246
      lval = (__typeof__(lval)) _res;                             \
4247
   } while (0)
4248
4249
#define CALL_FN_W_W(lval, orig, arg1)                             \
4250
   do {                                                           \
4251
      volatile OrigFn        _orig = (orig);                      \
4252
      volatile unsigned long _argvec[2];                          \
4253
      volatile unsigned long _res;                                \
4254
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4255
      _argvec[1] = (unsigned long)(arg1);                         \
4256
      __asm__ volatile(                                           \
4257
         VALGRIND_ALIGN_STACK                                     \
4258
         "ldr x0, [%1, #8] \n\t"                                  \
4259
         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4260
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4261
         VALGRIND_RESTORE_STACK                                   \
4262
         "mov %0, x0\n"                                           \
4263
         : /*out*/   "=r" (_res)                                  \
4264
         : /*in*/    "0" (&_argvec[0])                            \
4265
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4266
      );                                                          \
4267
      lval = (__typeof__(lval)) _res;                             \
4268
   } while (0)
4269
4270
#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
4271
   do {                                                           \
4272
      volatile OrigFn        _orig = (orig);                      \
4273
      volatile unsigned long _argvec[3];                          \
4274
      volatile unsigned long _res;                                \
4275
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4276
      _argvec[1] = (unsigned long)(arg1);                         \
4277
      _argvec[2] = (unsigned long)(arg2);                         \
4278
      __asm__ volatile(                                           \
4279
         VALGRIND_ALIGN_STACK                                     \
4280
         "ldr x0, [%1, #8] \n\t"                                  \
4281
         "ldr x1, [%1, #16] \n\t"                                 \
4282
         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4283
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4284
         VALGRIND_RESTORE_STACK                                   \
4285
         "mov %0, x0\n"                                           \
4286
         : /*out*/   "=r" (_res)                                  \
4287
         : /*in*/    "0" (&_argvec[0])                            \
4288
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4289
      );                                                          \
4290
      lval = (__typeof__(lval)) _res;                             \
4291
   } while (0)
4292
4293
#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
4294
   do {                                                           \
4295
      volatile OrigFn        _orig = (orig);                      \
4296
      volatile unsigned long _argvec[4];                          \
4297
      volatile unsigned long _res;                                \
4298
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4299
      _argvec[1] = (unsigned long)(arg1);                         \
4300
      _argvec[2] = (unsigned long)(arg2);                         \
4301
      _argvec[3] = (unsigned long)(arg3);                         \
4302
      __asm__ volatile(                                           \
4303
         VALGRIND_ALIGN_STACK                                     \
4304
         "ldr x0, [%1, #8] \n\t"                                  \
4305
         "ldr x1, [%1, #16] \n\t"                                 \
4306
         "ldr x2, [%1, #24] \n\t"                                 \
4307
         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4308
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4309
         VALGRIND_RESTORE_STACK                                   \
4310
         "mov %0, x0\n"                                           \
4311
         : /*out*/   "=r" (_res)                                  \
4312
         : /*in*/    "0" (&_argvec[0])                            \
4313
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4314
      );                                                          \
4315
      lval = (__typeof__(lval)) _res;                             \
4316
   } while (0)
4317
4318
#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
4319
   do {                                                           \
4320
      volatile OrigFn        _orig = (orig);                      \
4321
      volatile unsigned long _argvec[5];                          \
4322
      volatile unsigned long _res;                                \
4323
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4324
      _argvec[1] = (unsigned long)(arg1);                         \
4325
      _argvec[2] = (unsigned long)(arg2);                         \
4326
      _argvec[3] = (unsigned long)(arg3);                         \
4327
      _argvec[4] = (unsigned long)(arg4);                         \
4328
      __asm__ volatile(                                           \
4329
         VALGRIND_ALIGN_STACK                                     \
4330
         "ldr x0, [%1, #8] \n\t"                                  \
4331
         "ldr x1, [%1, #16] \n\t"                                 \
4332
         "ldr x2, [%1, #24] \n\t"                                 \
4333
         "ldr x3, [%1, #32] \n\t"                                 \
4334
         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4335
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4336
         VALGRIND_RESTORE_STACK                                   \
4337
         "mov %0, x0"                                             \
4338
         : /*out*/   "=r" (_res)                                  \
4339
         : /*in*/    "0" (&_argvec[0])                            \
4340
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4341
      );                                                          \
4342
      lval = (__typeof__(lval)) _res;                             \
4343
   } while (0)
4344
4345
#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
4346
   do {                                                           \
4347
      volatile OrigFn        _orig = (orig);                      \
4348
      volatile unsigned long _argvec[6];                          \
4349
      volatile unsigned long _res;                                \
4350
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4351
      _argvec[1] = (unsigned long)(arg1);                         \
4352
      _argvec[2] = (unsigned long)(arg2);                         \
4353
      _argvec[3] = (unsigned long)(arg3);                         \
4354
      _argvec[4] = (unsigned long)(arg4);                         \
4355
      _argvec[5] = (unsigned long)(arg5);                         \
4356
      __asm__ volatile(                                           \
4357
         VALGRIND_ALIGN_STACK                                     \
4358
         "ldr x0, [%1, #8] \n\t"                                  \
4359
         "ldr x1, [%1, #16] \n\t"                                 \
4360
         "ldr x2, [%1, #24] \n\t"                                 \
4361
         "ldr x3, [%1, #32] \n\t"                                 \
4362
         "ldr x4, [%1, #40] \n\t"                                 \
4363
         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4364
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4365
         VALGRIND_RESTORE_STACK                                   \
4366
         "mov %0, x0"                                             \
4367
         : /*out*/   "=r" (_res)                                  \
4368
         : /*in*/    "0" (&_argvec[0])                            \
4369
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4370
      );                                                          \
4371
      lval = (__typeof__(lval)) _res;                             \
4372
   } while (0)
4373
4374
#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
4375
   do {                                                           \
4376
      volatile OrigFn        _orig = (orig);                      \
4377
      volatile unsigned long _argvec[7];                          \
4378
      volatile unsigned long _res;                                \
4379
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4380
      _argvec[1] = (unsigned long)(arg1);                         \
4381
      _argvec[2] = (unsigned long)(arg2);                         \
4382
      _argvec[3] = (unsigned long)(arg3);                         \
4383
      _argvec[4] = (unsigned long)(arg4);                         \
4384
      _argvec[5] = (unsigned long)(arg5);                         \
4385
      _argvec[6] = (unsigned long)(arg6);                         \
4386
      __asm__ volatile(                                           \
4387
         VALGRIND_ALIGN_STACK                                     \
4388
         "ldr x0, [%1, #8] \n\t"                                  \
4389
         "ldr x1, [%1, #16] \n\t"                                 \
4390
         "ldr x2, [%1, #24] \n\t"                                 \
4391
         "ldr x3, [%1, #32] \n\t"                                 \
4392
         "ldr x4, [%1, #40] \n\t"                                 \
4393
         "ldr x5, [%1, #48] \n\t"                                 \
4394
         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4395
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4396
         VALGRIND_RESTORE_STACK                                   \
4397
         "mov %0, x0"                                             \
4398
         : /*out*/   "=r" (_res)                                  \
4399
         : /*in*/    "0" (&_argvec[0])                            \
4400
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4401
      );                                                          \
4402
      lval = (__typeof__(lval)) _res;                             \
4403
   } while (0)
4404
4405
#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
4406
                                 arg7)                            \
4407
   do {                                                           \
4408
      volatile OrigFn        _orig = (orig);                      \
4409
      volatile unsigned long _argvec[8];                          \
4410
      volatile unsigned long _res;                                \
4411
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4412
      _argvec[1] = (unsigned long)(arg1);                         \
4413
      _argvec[2] = (unsigned long)(arg2);                         \
4414
      _argvec[3] = (unsigned long)(arg3);                         \
4415
      _argvec[4] = (unsigned long)(arg4);                         \
4416
      _argvec[5] = (unsigned long)(arg5);                         \
4417
      _argvec[6] = (unsigned long)(arg6);                         \
4418
      _argvec[7] = (unsigned long)(arg7);                         \
4419
      __asm__ volatile(                                           \
4420
         VALGRIND_ALIGN_STACK                                     \
4421
         "ldr x0, [%1, #8] \n\t"                                  \
4422
         "ldr x1, [%1, #16] \n\t"                                 \
4423
         "ldr x2, [%1, #24] \n\t"                                 \
4424
         "ldr x3, [%1, #32] \n\t"                                 \
4425
         "ldr x4, [%1, #40] \n\t"                                 \
4426
         "ldr x5, [%1, #48] \n\t"                                 \
4427
         "ldr x6, [%1, #56] \n\t"                                 \
4428
         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4429
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4430
         VALGRIND_RESTORE_STACK                                   \
4431
         "mov %0, x0"                                             \
4432
         : /*out*/   "=r" (_res)                                  \
4433
         : /*in*/    "0" (&_argvec[0])                            \
4434
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4435
      );                                                          \
4436
      lval = (__typeof__(lval)) _res;                             \
4437
   } while (0)
4438
4439
#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
4440
                                 arg7,arg8)                       \
4441
   do {                                                           \
4442
      volatile OrigFn        _orig = (orig);                      \
4443
      volatile unsigned long _argvec[9];                          \
4444
      volatile unsigned long _res;                                \
4445
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4446
      _argvec[1] = (unsigned long)(arg1);                         \
4447
      _argvec[2] = (unsigned long)(arg2);                         \
4448
      _argvec[3] = (unsigned long)(arg3);                         \
4449
      _argvec[4] = (unsigned long)(arg4);                         \
4450
      _argvec[5] = (unsigned long)(arg5);                         \
4451
      _argvec[6] = (unsigned long)(arg6);                         \
4452
      _argvec[7] = (unsigned long)(arg7);                         \
4453
      _argvec[8] = (unsigned long)(arg8);                         \
4454
      __asm__ volatile(                                           \
4455
         VALGRIND_ALIGN_STACK                                     \
4456
         "ldr x0, [%1, #8] \n\t"                                  \
4457
         "ldr x1, [%1, #16] \n\t"                                 \
4458
         "ldr x2, [%1, #24] \n\t"                                 \
4459
         "ldr x3, [%1, #32] \n\t"                                 \
4460
         "ldr x4, [%1, #40] \n\t"                                 \
4461
         "ldr x5, [%1, #48] \n\t"                                 \
4462
         "ldr x6, [%1, #56] \n\t"                                 \
4463
         "ldr x7, [%1, #64] \n\t"                                 \
4464
         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4465
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4466
         VALGRIND_RESTORE_STACK                                   \
4467
         "mov %0, x0"                                             \
4468
         : /*out*/   "=r" (_res)                                  \
4469
         : /*in*/    "0" (&_argvec[0])                            \
4470
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4471
      );                                                          \
4472
      lval = (__typeof__(lval)) _res;                             \
4473
   } while (0)
4474
4475
#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
4476
                                 arg7,arg8,arg9)                  \
4477
   do {                                                           \
4478
      volatile OrigFn        _orig = (orig);                      \
4479
      volatile unsigned long _argvec[10];                         \
4480
      volatile unsigned long _res;                                \
4481
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4482
      _argvec[1] = (unsigned long)(arg1);                         \
4483
      _argvec[2] = (unsigned long)(arg2);                         \
4484
      _argvec[3] = (unsigned long)(arg3);                         \
4485
      _argvec[4] = (unsigned long)(arg4);                         \
4486
      _argvec[5] = (unsigned long)(arg5);                         \
4487
      _argvec[6] = (unsigned long)(arg6);                         \
4488
      _argvec[7] = (unsigned long)(arg7);                         \
4489
      _argvec[8] = (unsigned long)(arg8);                         \
4490
      _argvec[9] = (unsigned long)(arg9);                         \
4491
      __asm__ volatile(                                           \
4492
         VALGRIND_ALIGN_STACK                                     \
4493
         "sub sp, sp, #0x20 \n\t"                                 \
4494
         "ldr x0, [%1, #8] \n\t"                                  \
4495
         "ldr x1, [%1, #16] \n\t"                                 \
4496
         "ldr x2, [%1, #24] \n\t"                                 \
4497
         "ldr x3, [%1, #32] \n\t"                                 \
4498
         "ldr x4, [%1, #40] \n\t"                                 \
4499
         "ldr x5, [%1, #48] \n\t"                                 \
4500
         "ldr x6, [%1, #56] \n\t"                                 \
4501
         "ldr x7, [%1, #64] \n\t"                                 \
4502
         "ldr x8, [%1, #72] \n\t"                                 \
4503
         "str x8, [sp, #0]  \n\t"                                 \
4504
         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4505
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4506
         VALGRIND_RESTORE_STACK                                   \
4507
         "mov %0, x0"                                             \
4508
         : /*out*/   "=r" (_res)                                  \
4509
         : /*in*/    "0" (&_argvec[0])                            \
4510
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4511
      );                                                          \
4512
      lval = (__typeof__(lval)) _res;                             \
4513
   } while (0)
4514
4515
#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
4516
                                  arg7,arg8,arg9,arg10)           \
4517
   do {                                                           \
4518
      volatile OrigFn        _orig = (orig);                      \
4519
      volatile unsigned long _argvec[11];                         \
4520
      volatile unsigned long _res;                                \
4521
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4522
      _argvec[1] = (unsigned long)(arg1);                         \
4523
      _argvec[2] = (unsigned long)(arg2);                         \
4524
      _argvec[3] = (unsigned long)(arg3);                         \
4525
      _argvec[4] = (unsigned long)(arg4);                         \
4526
      _argvec[5] = (unsigned long)(arg5);                         \
4527
      _argvec[6] = (unsigned long)(arg6);                         \
4528
      _argvec[7] = (unsigned long)(arg7);                         \
4529
      _argvec[8] = (unsigned long)(arg8);                         \
4530
      _argvec[9] = (unsigned long)(arg9);                         \
4531
      _argvec[10] = (unsigned long)(arg10);                       \
4532
      __asm__ volatile(                                           \
4533
         VALGRIND_ALIGN_STACK                                     \
4534
         "sub sp, sp, #0x20 \n\t"                                 \
4535
         "ldr x0, [%1, #8] \n\t"                                  \
4536
         "ldr x1, [%1, #16] \n\t"                                 \
4537
         "ldr x2, [%1, #24] \n\t"                                 \
4538
         "ldr x3, [%1, #32] \n\t"                                 \
4539
         "ldr x4, [%1, #40] \n\t"                                 \
4540
         "ldr x5, [%1, #48] \n\t"                                 \
4541
         "ldr x6, [%1, #56] \n\t"                                 \
4542
         "ldr x7, [%1, #64] \n\t"                                 \
4543
         "ldr x8, [%1, #72] \n\t"                                 \
4544
         "str x8, [sp, #0]  \n\t"                                 \
4545
         "ldr x8, [%1, #80] \n\t"                                 \
4546
         "str x8, [sp, #8]  \n\t"                                 \
4547
         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4548
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4549
         VALGRIND_RESTORE_STACK                                   \
4550
         "mov %0, x0"                                             \
4551
         : /*out*/   "=r" (_res)                                  \
4552
         : /*in*/    "0" (&_argvec[0])                            \
4553
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4554
      );                                                          \
4555
      lval = (__typeof__(lval)) _res;                             \
4556
   } while (0)
4557
4558
#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
4559
                                  arg7,arg8,arg9,arg10,arg11)     \
4560
   do {                                                           \
4561
      volatile OrigFn        _orig = (orig);                      \
4562
      volatile unsigned long _argvec[12];                         \
4563
      volatile unsigned long _res;                                \
4564
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4565
      _argvec[1] = (unsigned long)(arg1);                         \
4566
      _argvec[2] = (unsigned long)(arg2);                         \
4567
      _argvec[3] = (unsigned long)(arg3);                         \
4568
      _argvec[4] = (unsigned long)(arg4);                         \
4569
      _argvec[5] = (unsigned long)(arg5);                         \
4570
      _argvec[6] = (unsigned long)(arg6);                         \
4571
      _argvec[7] = (unsigned long)(arg7);                         \
4572
      _argvec[8] = (unsigned long)(arg8);                         \
4573
      _argvec[9] = (unsigned long)(arg9);                         \
4574
      _argvec[10] = (unsigned long)(arg10);                       \
4575
      _argvec[11] = (unsigned long)(arg11);                       \
4576
      __asm__ volatile(                                           \
4577
         VALGRIND_ALIGN_STACK                                     \
4578
         "sub sp, sp, #0x30 \n\t"                                 \
4579
         "ldr x0, [%1, #8] \n\t"                                  \
4580
         "ldr x1, [%1, #16] \n\t"                                 \
4581
         "ldr x2, [%1, #24] \n\t"                                 \
4582
         "ldr x3, [%1, #32] \n\t"                                 \
4583
         "ldr x4, [%1, #40] \n\t"                                 \
4584
         "ldr x5, [%1, #48] \n\t"                                 \
4585
         "ldr x6, [%1, #56] \n\t"                                 \
4586
         "ldr x7, [%1, #64] \n\t"                                 \
4587
         "ldr x8, [%1, #72] \n\t"                                 \
4588
         "str x8, [sp, #0]  \n\t"                                 \
4589
         "ldr x8, [%1, #80] \n\t"                                 \
4590
         "str x8, [sp, #8]  \n\t"                                 \
4591
         "ldr x8, [%1, #88] \n\t"                                 \
4592
         "str x8, [sp, #16] \n\t"                                 \
4593
         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4594
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4595
         VALGRIND_RESTORE_STACK                                   \
4596
         "mov %0, x0"                                             \
4597
         : /*out*/   "=r" (_res)                                  \
4598
         : /*in*/    "0" (&_argvec[0])                            \
4599
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4600
      );                                                          \
4601
      lval = (__typeof__(lval)) _res;                             \
4602
   } while (0)
4603
4604
#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
4605
                                  arg7,arg8,arg9,arg10,arg11,     \
4606
                                  arg12)                          \
4607
   do {                                                           \
4608
      volatile OrigFn        _orig = (orig);                      \
4609
      volatile unsigned long _argvec[13];                         \
4610
      volatile unsigned long _res;                                \
4611
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
4612
      _argvec[1] = (unsigned long)(arg1);                         \
4613
      _argvec[2] = (unsigned long)(arg2);                         \
4614
      _argvec[3] = (unsigned long)(arg3);                         \
4615
      _argvec[4] = (unsigned long)(arg4);                         \
4616
      _argvec[5] = (unsigned long)(arg5);                         \
4617
      _argvec[6] = (unsigned long)(arg6);                         \
4618
      _argvec[7] = (unsigned long)(arg7);                         \
4619
      _argvec[8] = (unsigned long)(arg8);                         \
4620
      _argvec[9] = (unsigned long)(arg9);                         \
4621
      _argvec[10] = (unsigned long)(arg10);                       \
4622
      _argvec[11] = (unsigned long)(arg11);                       \
4623
      _argvec[12] = (unsigned long)(arg12);                       \
4624
      __asm__ volatile(                                           \
4625
         VALGRIND_ALIGN_STACK                                     \
4626
         "sub sp, sp, #0x30 \n\t"                                 \
4627
         "ldr x0, [%1, #8] \n\t"                                  \
4628
         "ldr x1, [%1, #16] \n\t"                                 \
4629
         "ldr x2, [%1, #24] \n\t"                                 \
4630
         "ldr x3, [%1, #32] \n\t"                                 \
4631
         "ldr x4, [%1, #40] \n\t"                                 \
4632
         "ldr x5, [%1, #48] \n\t"                                 \
4633
         "ldr x6, [%1, #56] \n\t"                                 \
4634
         "ldr x7, [%1, #64] \n\t"                                 \
4635
         "ldr x8, [%1, #72] \n\t"                                 \
4636
         "str x8, [sp, #0]  \n\t"                                 \
4637
         "ldr x8, [%1, #80] \n\t"                                 \
4638
         "str x8, [sp, #8]  \n\t"                                 \
4639
         "ldr x8, [%1, #88] \n\t"                                 \
4640
         "str x8, [sp, #16] \n\t"                                 \
4641
         "ldr x8, [%1, #96] \n\t"                                 \
4642
         "str x8, [sp, #24] \n\t"                                 \
4643
         "ldr x8, [%1] \n\t"  /* target->x8 */                    \
4644
         VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8                   \
4645
         VALGRIND_RESTORE_STACK                                   \
4646
         "mov %0, x0"                                             \
4647
         : /*out*/   "=r" (_res)                                  \
4648
         : /*in*/    "0" (&_argvec[0])                            \
4649
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21"   \
4650
      );                                                          \
4651
      lval = (__typeof__(lval)) _res;                             \
4652
   } while (0)
4653
4654
#endif /* PLAT_arm64_linux */
4655
4656
/* ------------------------- s390x-linux ------------------------- */
4657
4658
#if defined(PLAT_s390x_linux)
4659
4660
/* Similar workaround as amd64 (see above), but we use r11 as frame
4661
   pointer and save the old r11 in r7. r11 might be used for
4662
   argvec, therefore we copy argvec in r1 since r1 is clobbered
4663
   after the call anyway.  */
4664
#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
4665
#  define __FRAME_POINTER                                         \
4666
      ,"d"(__builtin_dwarf_cfa())
4667
#  define VALGRIND_CFI_PROLOGUE                                   \
4668
      ".cfi_remember_state\n\t"                                   \
4669
      "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */          \
4670
      "lgr 7,11\n\t"                                              \
4671
      "lgr 11,%2\n\t"                                             \
4672
      ".cfi_def_cfa r11, 0\n\t"
4673
#  define VALGRIND_CFI_EPILOGUE                                   \
4674
      "lgr 11, 7\n\t"                                             \
4675
      ".cfi_restore_state\n\t"
4676
#else
4677
#  define __FRAME_POINTER
4678
#  define VALGRIND_CFI_PROLOGUE                                   \
4679
      "lgr 1,%1\n\t"
4680
#  define VALGRIND_CFI_EPILOGUE
4681
#endif
4682
4683
/* Nb: On s390 the stack pointer is properly aligned *at all times*
4684
   according to the s390 GCC maintainer. (The ABI specification is not
4685
   precise in this regard.) Therefore, VALGRIND_ALIGN_STACK and
4686
   VALGRIND_RESTORE_STACK are not defined here. */
4687
4688
/* These regs are trashed by the hidden call. Note that we overwrite
4689
   r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
4690
   function a proper return address. All others are ABI defined call
4691
   clobbers. */
4692
#define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \
4693
                           "f0","f1","f2","f3","f4","f5","f6","f7"
4694
4695
/* Nb: Although r11 is modified in the asm snippets below (inside 
4696
   VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for
4697
   two reasons:
4698
   (1) r11 is restored in VALGRIND_CFI_EPILOGUE, so effectively it is not
4699
       modified
4700
   (2) GCC will complain that r11 cannot appear inside a clobber section,
4701
       when compiled with -O -fno-omit-frame-pointer
4702
 */
4703
4704
#define CALL_FN_W_v(lval, orig)                                  \
4705
   do {                                                          \
4706
      volatile OrigFn        _orig = (orig);                     \
4707
      volatile unsigned long  _argvec[1];                        \
4708
      volatile unsigned long _res;                               \
4709
      _argvec[0] = (unsigned long)_orig.nraddr;                  \
4710
      __asm__ volatile(                                          \
4711
         VALGRIND_CFI_PROLOGUE                                   \
4712
         "aghi 15,-160\n\t"                                      \
4713
         "lg 1, 0(1)\n\t"  /* target->r1 */                      \
4714
         VALGRIND_CALL_NOREDIR_R1                                \
4715
         "lgr %0, 2\n\t"                                         \
4716
         "aghi 15,160\n\t"                                       \
4717
         VALGRIND_CFI_EPILOGUE                                   \
4718
         : /*out*/   "=d" (_res)                                 \
4719
         : /*in*/    "d" (&_argvec[0]) __FRAME_POINTER           \
4720
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7"     \
4721
      );                                                         \
4722
      lval = (__typeof__(lval)) _res;                            \
4723
   } while (0)
4724
4725
/* The call abi has the arguments in r2-r6 and stack */
4726
#define CALL_FN_W_W(lval, orig, arg1)                            \
4727
   do {                                                          \
4728
      volatile OrigFn        _orig = (orig);                     \
4729
      volatile unsigned long _argvec[2];                         \
4730
      volatile unsigned long _res;                               \
4731
      _argvec[0] = (unsigned long)_orig.nraddr;                  \
4732
      _argvec[1] = (unsigned long)arg1;                          \
4733
      __asm__ volatile(                                          \
4734
         VALGRIND_CFI_PROLOGUE                                   \
4735
         "aghi 15,-160\n\t"                                      \
4736
         "lg 2, 8(1)\n\t"                                        \
4737
         "lg 1, 0(1)\n\t"                                        \
4738
         VALGRIND_CALL_NOREDIR_R1                                \
4739
         "lgr %0, 2\n\t"                                         \
4740
         "aghi 15,160\n\t"                                       \
4741
         VALGRIND_CFI_EPILOGUE                                   \
4742
         : /*out*/   "=d" (_res)                                 \
4743
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4744
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7"     \
4745
      );                                                         \
4746
      lval = (__typeof__(lval)) _res;                            \
4747
   } while (0)
4748
4749
#define CALL_FN_W_WW(lval, orig, arg1, arg2)                     \
4750
   do {                                                          \
4751
      volatile OrigFn        _orig = (orig);                     \
4752
      volatile unsigned long _argvec[3];                         \
4753
      volatile unsigned long _res;                               \
4754
      _argvec[0] = (unsigned long)_orig.nraddr;                  \
4755
      _argvec[1] = (unsigned long)arg1;                          \
4756
      _argvec[2] = (unsigned long)arg2;                          \
4757
      __asm__ volatile(                                          \
4758
         VALGRIND_CFI_PROLOGUE                                   \
4759
         "aghi 15,-160\n\t"                                      \
4760
         "lg 2, 8(1)\n\t"                                        \
4761
         "lg 3,16(1)\n\t"                                        \
4762
         "lg 1, 0(1)\n\t"                                        \
4763
         VALGRIND_CALL_NOREDIR_R1                                \
4764
         "lgr %0, 2\n\t"                                         \
4765
         "aghi 15,160\n\t"                                       \
4766
         VALGRIND_CFI_EPILOGUE                                   \
4767
         : /*out*/   "=d" (_res)                                 \
4768
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4769
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7"     \
4770
      );                                                         \
4771
      lval = (__typeof__(lval)) _res;                            \
4772
   } while (0)
4773
4774
#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3)              \
4775
   do {                                                          \
4776
      volatile OrigFn        _orig = (orig);                     \
4777
      volatile unsigned long _argvec[4];                         \
4778
      volatile unsigned long _res;                               \
4779
      _argvec[0] = (unsigned long)_orig.nraddr;                  \
4780
      _argvec[1] = (unsigned long)arg1;                          \
4781
      _argvec[2] = (unsigned long)arg2;                          \
4782
      _argvec[3] = (unsigned long)arg3;                          \
4783
      __asm__ volatile(                                          \
4784
         VALGRIND_CFI_PROLOGUE                                   \
4785
         "aghi 15,-160\n\t"                                      \
4786
         "lg 2, 8(1)\n\t"                                        \
4787
         "lg 3,16(1)\n\t"                                        \
4788
         "lg 4,24(1)\n\t"                                        \
4789
         "lg 1, 0(1)\n\t"                                        \
4790
         VALGRIND_CALL_NOREDIR_R1                                \
4791
         "lgr %0, 2\n\t"                                         \
4792
         "aghi 15,160\n\t"                                       \
4793
         VALGRIND_CFI_EPILOGUE                                   \
4794
         : /*out*/   "=d" (_res)                                 \
4795
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4796
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7"     \
4797
      );                                                         \
4798
      lval = (__typeof__(lval)) _res;                            \
4799
   } while (0)
4800
4801
#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4)       \
4802
   do {                                                          \
4803
      volatile OrigFn        _orig = (orig);                     \
4804
      volatile unsigned long _argvec[5];                         \
4805
      volatile unsigned long _res;                               \
4806
      _argvec[0] = (unsigned long)_orig.nraddr;                  \
4807
      _argvec[1] = (unsigned long)arg1;                          \
4808
      _argvec[2] = (unsigned long)arg2;                          \
4809
      _argvec[3] = (unsigned long)arg3;                          \
4810
      _argvec[4] = (unsigned long)arg4;                          \
4811
      __asm__ volatile(                                          \
4812
         VALGRIND_CFI_PROLOGUE                                   \
4813
         "aghi 15,-160\n\t"                                      \
4814
         "lg 2, 8(1)\n\t"                                        \
4815
         "lg 3,16(1)\n\t"                                        \
4816
         "lg 4,24(1)\n\t"                                        \
4817
         "lg 5,32(1)\n\t"                                        \
4818
         "lg 1, 0(1)\n\t"                                        \
4819
         VALGRIND_CALL_NOREDIR_R1                                \
4820
         "lgr %0, 2\n\t"                                         \
4821
         "aghi 15,160\n\t"                                       \
4822
         VALGRIND_CFI_EPILOGUE                                   \
4823
         : /*out*/   "=d" (_res)                                 \
4824
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4825
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7"     \
4826
      );                                                         \
4827
      lval = (__typeof__(lval)) _res;                            \
4828
   } while (0)
4829
4830
#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5)   \
4831
   do {                                                          \
4832
      volatile OrigFn        _orig = (orig);                     \
4833
      volatile unsigned long _argvec[6];                         \
4834
      volatile unsigned long _res;                               \
4835
      _argvec[0] = (unsigned long)_orig.nraddr;                  \
4836
      _argvec[1] = (unsigned long)arg1;                          \
4837
      _argvec[2] = (unsigned long)arg2;                          \
4838
      _argvec[3] = (unsigned long)arg3;                          \
4839
      _argvec[4] = (unsigned long)arg4;                          \
4840
      _argvec[5] = (unsigned long)arg5;                          \
4841
      __asm__ volatile(                                          \
4842
         VALGRIND_CFI_PROLOGUE                                   \
4843
         "aghi 15,-160\n\t"                                      \
4844
         "lg 2, 8(1)\n\t"                                        \
4845
         "lg 3,16(1)\n\t"                                        \
4846
         "lg 4,24(1)\n\t"                                        \
4847
         "lg 5,32(1)\n\t"                                        \
4848
         "lg 6,40(1)\n\t"                                        \
4849
         "lg 1, 0(1)\n\t"                                        \
4850
         VALGRIND_CALL_NOREDIR_R1                                \
4851
         "lgr %0, 2\n\t"                                         \
4852
         "aghi 15,160\n\t"                                       \
4853
         VALGRIND_CFI_EPILOGUE                                   \
4854
         : /*out*/   "=d" (_res)                                 \
4855
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4856
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4857
      );                                                         \
4858
      lval = (__typeof__(lval)) _res;                            \
4859
   } while (0)
4860
4861
#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5,   \
4862
                     arg6)                                       \
4863
   do {                                                          \
4864
      volatile OrigFn        _orig = (orig);                     \
4865
      volatile unsigned long _argvec[7];                         \
4866
      volatile unsigned long _res;                               \
4867
      _argvec[0] = (unsigned long)_orig.nraddr;                  \
4868
      _argvec[1] = (unsigned long)arg1;                          \
4869
      _argvec[2] = (unsigned long)arg2;                          \
4870
      _argvec[3] = (unsigned long)arg3;                          \
4871
      _argvec[4] = (unsigned long)arg4;                          \
4872
      _argvec[5] = (unsigned long)arg5;                          \
4873
      _argvec[6] = (unsigned long)arg6;                          \
4874
      __asm__ volatile(                                          \
4875
         VALGRIND_CFI_PROLOGUE                                   \
4876
         "aghi 15,-168\n\t"                                      \
4877
         "lg 2, 8(1)\n\t"                                        \
4878
         "lg 3,16(1)\n\t"                                        \
4879
         "lg 4,24(1)\n\t"                                        \
4880
         "lg 5,32(1)\n\t"                                        \
4881
         "lg 6,40(1)\n\t"                                        \
4882
         "mvc 160(8,15), 48(1)\n\t"                              \
4883
         "lg 1, 0(1)\n\t"                                        \
4884
         VALGRIND_CALL_NOREDIR_R1                                \
4885
         "lgr %0, 2\n\t"                                         \
4886
         "aghi 15,168\n\t"                                       \
4887
         VALGRIND_CFI_EPILOGUE                                   \
4888
         : /*out*/   "=d" (_res)                                 \
4889
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4890
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4891
      );                                                         \
4892
      lval = (__typeof__(lval)) _res;                            \
4893
   } while (0)
4894
4895
#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5,   \
4896
                     arg6, arg7)                                 \
4897
   do {                                                          \
4898
      volatile OrigFn        _orig = (orig);                     \
4899
      volatile unsigned long _argvec[8];                         \
4900
      volatile unsigned long _res;                               \
4901
      _argvec[0] = (unsigned long)_orig.nraddr;                  \
4902
      _argvec[1] = (unsigned long)arg1;                          \
4903
      _argvec[2] = (unsigned long)arg2;                          \
4904
      _argvec[3] = (unsigned long)arg3;                          \
4905
      _argvec[4] = (unsigned long)arg4;                          \
4906
      _argvec[5] = (unsigned long)arg5;                          \
4907
      _argvec[6] = (unsigned long)arg6;                          \
4908
      _argvec[7] = (unsigned long)arg7;                          \
4909
      __asm__ volatile(                                          \
4910
         VALGRIND_CFI_PROLOGUE                                   \
4911
         "aghi 15,-176\n\t"                                      \
4912
         "lg 2, 8(1)\n\t"                                        \
4913
         "lg 3,16(1)\n\t"                                        \
4914
         "lg 4,24(1)\n\t"                                        \
4915
         "lg 5,32(1)\n\t"                                        \
4916
         "lg 6,40(1)\n\t"                                        \
4917
         "mvc 160(8,15), 48(1)\n\t"                              \
4918
         "mvc 168(8,15), 56(1)\n\t"                              \
4919
         "lg 1, 0(1)\n\t"                                        \
4920
         VALGRIND_CALL_NOREDIR_R1                                \
4921
         "lgr %0, 2\n\t"                                         \
4922
         "aghi 15,176\n\t"                                       \
4923
         VALGRIND_CFI_EPILOGUE                                   \
4924
         : /*out*/   "=d" (_res)                                 \
4925
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4926
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4927
      );                                                         \
4928
      lval = (__typeof__(lval)) _res;                            \
4929
   } while (0)
4930
4931
#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5,   \
4932
                     arg6, arg7 ,arg8)                           \
4933
   do {                                                          \
4934
      volatile OrigFn        _orig = (orig);                     \
4935
      volatile unsigned long _argvec[9];                         \
4936
      volatile unsigned long _res;                               \
4937
      _argvec[0] = (unsigned long)_orig.nraddr;                  \
4938
      _argvec[1] = (unsigned long)arg1;                          \
4939
      _argvec[2] = (unsigned long)arg2;                          \
4940
      _argvec[3] = (unsigned long)arg3;                          \
4941
      _argvec[4] = (unsigned long)arg4;                          \
4942
      _argvec[5] = (unsigned long)arg5;                          \
4943
      _argvec[6] = (unsigned long)arg6;                          \
4944
      _argvec[7] = (unsigned long)arg7;                          \
4945
      _argvec[8] = (unsigned long)arg8;                          \
4946
      __asm__ volatile(                                          \
4947
         VALGRIND_CFI_PROLOGUE                                   \
4948
         "aghi 15,-184\n\t"                                      \
4949
         "lg 2, 8(1)\n\t"                                        \
4950
         "lg 3,16(1)\n\t"                                        \
4951
         "lg 4,24(1)\n\t"                                        \
4952
         "lg 5,32(1)\n\t"                                        \
4953
         "lg 6,40(1)\n\t"                                        \
4954
         "mvc 160(8,15), 48(1)\n\t"                              \
4955
         "mvc 168(8,15), 56(1)\n\t"                              \
4956
         "mvc 176(8,15), 64(1)\n\t"                              \
4957
         "lg 1, 0(1)\n\t"                                        \
4958
         VALGRIND_CALL_NOREDIR_R1                                \
4959
         "lgr %0, 2\n\t"                                         \
4960
         "aghi 15,184\n\t"                                       \
4961
         VALGRIND_CFI_EPILOGUE                                   \
4962
         : /*out*/   "=d" (_res)                                 \
4963
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
4964
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
4965
      );                                                         \
4966
      lval = (__typeof__(lval)) _res;                            \
4967
   } while (0)
4968
4969
#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5,   \
4970
                     arg6, arg7 ,arg8, arg9)                     \
4971
   do {                                                          \
4972
      volatile OrigFn        _orig = (orig);                     \
4973
      volatile unsigned long _argvec[10];                        \
4974
      volatile unsigned long _res;                               \
4975
      _argvec[0] = (unsigned long)_orig.nraddr;                  \
4976
      _argvec[1] = (unsigned long)arg1;                          \
4977
      _argvec[2] = (unsigned long)arg2;                          \
4978
      _argvec[3] = (unsigned long)arg3;                          \
4979
      _argvec[4] = (unsigned long)arg4;                          \
4980
      _argvec[5] = (unsigned long)arg5;                          \
4981
      _argvec[6] = (unsigned long)arg6;                          \
4982
      _argvec[7] = (unsigned long)arg7;                          \
4983
      _argvec[8] = (unsigned long)arg8;                          \
4984
      _argvec[9] = (unsigned long)arg9;                          \
4985
      __asm__ volatile(                                          \
4986
         VALGRIND_CFI_PROLOGUE                                   \
4987
         "aghi 15,-192\n\t"                                      \
4988
         "lg 2, 8(1)\n\t"                                        \
4989
         "lg 3,16(1)\n\t"                                        \
4990
         "lg 4,24(1)\n\t"                                        \
4991
         "lg 5,32(1)\n\t"                                        \
4992
         "lg 6,40(1)\n\t"                                        \
4993
         "mvc 160(8,15), 48(1)\n\t"                              \
4994
         "mvc 168(8,15), 56(1)\n\t"                              \
4995
         "mvc 176(8,15), 64(1)\n\t"                              \
4996
         "mvc 184(8,15), 72(1)\n\t"                              \
4997
         "lg 1, 0(1)\n\t"                                        \
4998
         VALGRIND_CALL_NOREDIR_R1                                \
4999
         "lgr %0, 2\n\t"                                         \
5000
         "aghi 15,192\n\t"                                       \
5001
         VALGRIND_CFI_EPILOGUE                                   \
5002
         : /*out*/   "=d" (_res)                                 \
5003
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
5004
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5005
      );                                                         \
5006
      lval = (__typeof__(lval)) _res;                            \
5007
   } while (0)
5008
5009
#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5,  \
5010
                     arg6, arg7 ,arg8, arg9, arg10)              \
5011
   do {                                                          \
5012
      volatile OrigFn        _orig = (orig);                     \
5013
      volatile unsigned long _argvec[11];                        \
5014
      volatile unsigned long _res;                               \
5015
      _argvec[0] = (unsigned long)_orig.nraddr;                  \
5016
      _argvec[1] = (unsigned long)arg1;                          \
5017
      _argvec[2] = (unsigned long)arg2;                          \
5018
      _argvec[3] = (unsigned long)arg3;                          \
5019
      _argvec[4] = (unsigned long)arg4;                          \
5020
      _argvec[5] = (unsigned long)arg5;                          \
5021
      _argvec[6] = (unsigned long)arg6;                          \
5022
      _argvec[7] = (unsigned long)arg7;                          \
5023
      _argvec[8] = (unsigned long)arg8;                          \
5024
      _argvec[9] = (unsigned long)arg9;                          \
5025
      _argvec[10] = (unsigned long)arg10;                        \
5026
      __asm__ volatile(                                          \
5027
         VALGRIND_CFI_PROLOGUE                                   \
5028
         "aghi 15,-200\n\t"                                      \
5029
         "lg 2, 8(1)\n\t"                                        \
5030
         "lg 3,16(1)\n\t"                                        \
5031
         "lg 4,24(1)\n\t"                                        \
5032
         "lg 5,32(1)\n\t"                                        \
5033
         "lg 6,40(1)\n\t"                                        \
5034
         "mvc 160(8,15), 48(1)\n\t"                              \
5035
         "mvc 168(8,15), 56(1)\n\t"                              \
5036
         "mvc 176(8,15), 64(1)\n\t"                              \
5037
         "mvc 184(8,15), 72(1)\n\t"                              \
5038
         "mvc 192(8,15), 80(1)\n\t"                              \
5039
         "lg 1, 0(1)\n\t"                                        \
5040
         VALGRIND_CALL_NOREDIR_R1                                \
5041
         "lgr %0, 2\n\t"                                         \
5042
         "aghi 15,200\n\t"                                       \
5043
         VALGRIND_CFI_EPILOGUE                                   \
5044
         : /*out*/   "=d" (_res)                                 \
5045
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
5046
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5047
      );                                                         \
5048
      lval = (__typeof__(lval)) _res;                            \
5049
   } while (0)
5050
5051
#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5,  \
5052
                     arg6, arg7 ,arg8, arg9, arg10, arg11)       \
5053
   do {                                                          \
5054
      volatile OrigFn        _orig = (orig);                     \
5055
      volatile unsigned long _argvec[12];                        \
5056
      volatile unsigned long _res;                               \
5057
      _argvec[0] = (unsigned long)_orig.nraddr;                  \
5058
      _argvec[1] = (unsigned long)arg1;                          \
5059
      _argvec[2] = (unsigned long)arg2;                          \
5060
      _argvec[3] = (unsigned long)arg3;                          \
5061
      _argvec[4] = (unsigned long)arg4;                          \
5062
      _argvec[5] = (unsigned long)arg5;                          \
5063
      _argvec[6] = (unsigned long)arg6;                          \
5064
      _argvec[7] = (unsigned long)arg7;                          \
5065
      _argvec[8] = (unsigned long)arg8;                          \
5066
      _argvec[9] = (unsigned long)arg9;                          \
5067
      _argvec[10] = (unsigned long)arg10;                        \
5068
      _argvec[11] = (unsigned long)arg11;                        \
5069
      __asm__ volatile(                                          \
5070
         VALGRIND_CFI_PROLOGUE                                   \
5071
         "aghi 15,-208\n\t"                                      \
5072
         "lg 2, 8(1)\n\t"                                        \
5073
         "lg 3,16(1)\n\t"                                        \
5074
         "lg 4,24(1)\n\t"                                        \
5075
         "lg 5,32(1)\n\t"                                        \
5076
         "lg 6,40(1)\n\t"                                        \
5077
         "mvc 160(8,15), 48(1)\n\t"                              \
5078
         "mvc 168(8,15), 56(1)\n\t"                              \
5079
         "mvc 176(8,15), 64(1)\n\t"                              \
5080
         "mvc 184(8,15), 72(1)\n\t"                              \
5081
         "mvc 192(8,15), 80(1)\n\t"                              \
5082
         "mvc 200(8,15), 88(1)\n\t"                              \
5083
         "lg 1, 0(1)\n\t"                                        \
5084
         VALGRIND_CALL_NOREDIR_R1                                \
5085
         "lgr %0, 2\n\t"                                         \
5086
         "aghi 15,208\n\t"                                       \
5087
         VALGRIND_CFI_EPILOGUE                                   \
5088
         : /*out*/   "=d" (_res)                                 \
5089
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
5090
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5091
      );                                                         \
5092
      lval = (__typeof__(lval)) _res;                            \
5093
   } while (0)
5094
5095
#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5,  \
5096
                     arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\
5097
   do {                                                          \
5098
      volatile OrigFn        _orig = (orig);                     \
5099
      volatile unsigned long _argvec[13];                        \
5100
      volatile unsigned long _res;                               \
5101
      _argvec[0] = (unsigned long)_orig.nraddr;                  \
5102
      _argvec[1] = (unsigned long)arg1;                          \
5103
      _argvec[2] = (unsigned long)arg2;                          \
5104
      _argvec[3] = (unsigned long)arg3;                          \
5105
      _argvec[4] = (unsigned long)arg4;                          \
5106
      _argvec[5] = (unsigned long)arg5;                          \
5107
      _argvec[6] = (unsigned long)arg6;                          \
5108
      _argvec[7] = (unsigned long)arg7;                          \
5109
      _argvec[8] = (unsigned long)arg8;                          \
5110
      _argvec[9] = (unsigned long)arg9;                          \
5111
      _argvec[10] = (unsigned long)arg10;                        \
5112
      _argvec[11] = (unsigned long)arg11;                        \
5113
      _argvec[12] = (unsigned long)arg12;                        \
5114
      __asm__ volatile(                                          \
5115
         VALGRIND_CFI_PROLOGUE                                   \
5116
         "aghi 15,-216\n\t"                                      \
5117
         "lg 2, 8(1)\n\t"                                        \
5118
         "lg 3,16(1)\n\t"                                        \
5119
         "lg 4,24(1)\n\t"                                        \
5120
         "lg 5,32(1)\n\t"                                        \
5121
         "lg 6,40(1)\n\t"                                        \
5122
         "mvc 160(8,15), 48(1)\n\t"                              \
5123
         "mvc 168(8,15), 56(1)\n\t"                              \
5124
         "mvc 176(8,15), 64(1)\n\t"                              \
5125
         "mvc 184(8,15), 72(1)\n\t"                              \
5126
         "mvc 192(8,15), 80(1)\n\t"                              \
5127
         "mvc 200(8,15), 88(1)\n\t"                              \
5128
         "mvc 208(8,15), 96(1)\n\t"                              \
5129
         "lg 1, 0(1)\n\t"                                        \
5130
         VALGRIND_CALL_NOREDIR_R1                                \
5131
         "lgr %0, 2\n\t"                                         \
5132
         "aghi 15,216\n\t"                                       \
5133
         VALGRIND_CFI_EPILOGUE                                   \
5134
         : /*out*/   "=d" (_res)                                 \
5135
         : /*in*/    "a" (&_argvec[0]) __FRAME_POINTER           \
5136
         : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
5137
      );                                                         \
5138
      lval = (__typeof__(lval)) _res;                            \
5139
   } while (0)
5140
5141
5142
#endif /* PLAT_s390x_linux */
5143
5144
/* ------------------------- mips32-linux ----------------------- */
5145
 
5146
#if defined(PLAT_mips32_linux)
5147
5148
/* These regs are trashed by the hidden call. */
5149
#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6",       \
5150
"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
5151
"$25", "$31"
5152
5153
/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
5154
   long) == 4. */
5155
5156
#define CALL_FN_W_v(lval, orig)                                   \
5157
   do {                                                           \
5158
      volatile OrigFn        _orig = (orig);                      \
5159
      volatile unsigned long _argvec[1];                          \
5160
      volatile unsigned long _res;                                \
5161
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5162
      __asm__ volatile(                                           \
5163
         "subu $29, $29, 8 \n\t"                                  \
5164
         "sw $28, 0($29) \n\t"                                    \
5165
         "sw $31, 4($29) \n\t"                                    \
5166
         "subu $29, $29, 16 \n\t"                                 \
5167
         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5168
         VALGRIND_CALL_NOREDIR_T9                                 \
5169
         "addu $29, $29, 16\n\t"                                  \
5170
         "lw $28, 0($29) \n\t"                                    \
5171
         "lw $31, 4($29) \n\t"                                    \
5172
         "addu $29, $29, 8 \n\t"                                  \
5173
         "move %0, $2\n"                                          \
5174
         : /*out*/   "=r" (_res)                                  \
5175
         : /*in*/    "0" (&_argvec[0])                            \
5176
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5177
      );                                                          \
5178
      lval = (__typeof__(lval)) _res;                             \
5179
   } while (0)
5180
5181
#define CALL_FN_W_W(lval, orig, arg1)                             \
5182
   do {                                                           \
5183
      volatile OrigFn        _orig = (orig);                      \
5184
     volatile unsigned long _argvec[2];                           \
5185
      volatile unsigned long _res;                                \
5186
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5187
      _argvec[1] = (unsigned long)(arg1);                         \
5188
      __asm__ volatile(                                           \
5189
         "subu $29, $29, 8 \n\t"                                  \
5190
         "sw $28, 0($29) \n\t"                                    \
5191
         "sw $31, 4($29) \n\t"                                    \
5192
         "subu $29, $29, 16 \n\t"                                 \
5193
         "lw $4, 4(%1) \n\t"   /* arg1*/                          \
5194
         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5195
         VALGRIND_CALL_NOREDIR_T9                                 \
5196
         "addu $29, $29, 16 \n\t"                                 \
5197
         "lw $28, 0($29) \n\t"                                    \
5198
         "lw $31, 4($29) \n\t"                                    \
5199
         "addu $29, $29, 8 \n\t"                                  \
5200
         "move %0, $2\n"                                          \
5201
         : /*out*/   "=r" (_res)                                  \
5202
         : /*in*/    "0" (&_argvec[0])                            \
5203
         : /*trash*/ "memory",  __CALLER_SAVED_REGS               \
5204
      );                                                          \
5205
      lval = (__typeof__(lval)) _res;                             \
5206
   } while (0)
5207
5208
#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
5209
   do {                                                           \
5210
      volatile OrigFn        _orig = (orig);                      \
5211
      volatile unsigned long _argvec[3];                          \
5212
      volatile unsigned long _res;                                \
5213
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5214
      _argvec[1] = (unsigned long)(arg1);                         \
5215
      _argvec[2] = (unsigned long)(arg2);                         \
5216
      __asm__ volatile(                                           \
5217
         "subu $29, $29, 8 \n\t"                                  \
5218
         "sw $28, 0($29) \n\t"                                    \
5219
         "sw $31, 4($29) \n\t"                                    \
5220
         "subu $29, $29, 16 \n\t"                                 \
5221
         "lw $4, 4(%1) \n\t"                                      \
5222
         "lw $5, 8(%1) \n\t"                                      \
5223
         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5224
         VALGRIND_CALL_NOREDIR_T9                                 \
5225
         "addu $29, $29, 16 \n\t"                                 \
5226
         "lw $28, 0($29) \n\t"                                    \
5227
         "lw $31, 4($29) \n\t"                                    \
5228
         "addu $29, $29, 8 \n\t"                                  \
5229
         "move %0, $2\n"                                          \
5230
         : /*out*/   "=r" (_res)                                  \
5231
         : /*in*/    "0" (&_argvec[0])                            \
5232
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5233
      );                                                          \
5234
      lval = (__typeof__(lval)) _res;                             \
5235
   } while (0)
5236
5237
#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
5238
   do {                                                           \
5239
      volatile OrigFn        _orig = (orig);                      \
5240
      volatile unsigned long _argvec[4];                          \
5241
      volatile unsigned long _res;                                \
5242
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5243
      _argvec[1] = (unsigned long)(arg1);                         \
5244
      _argvec[2] = (unsigned long)(arg2);                         \
5245
      _argvec[3] = (unsigned long)(arg3);                         \
5246
      __asm__ volatile(                                           \
5247
         "subu $29, $29, 8 \n\t"                                  \
5248
         "sw $28, 0($29) \n\t"                                    \
5249
         "sw $31, 4($29) \n\t"                                    \
5250
         "subu $29, $29, 16 \n\t"                                 \
5251
         "lw $4, 4(%1) \n\t"                                      \
5252
         "lw $5, 8(%1) \n\t"                                      \
5253
         "lw $6, 12(%1) \n\t"                                     \
5254
         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5255
         VALGRIND_CALL_NOREDIR_T9                                 \
5256
         "addu $29, $29, 16 \n\t"                                 \
5257
         "lw $28, 0($29) \n\t"                                    \
5258
         "lw $31, 4($29) \n\t"                                    \
5259
         "addu $29, $29, 8 \n\t"                                  \
5260
         "move %0, $2\n"                                          \
5261
         : /*out*/   "=r" (_res)                                  \
5262
         : /*in*/    "0" (&_argvec[0])                            \
5263
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5264
      );                                                          \
5265
      lval = (__typeof__(lval)) _res;                             \
5266
   } while (0)
5267
5268
#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
5269
   do {                                                           \
5270
      volatile OrigFn        _orig = (orig);                      \
5271
      volatile unsigned long _argvec[5];                          \
5272
      volatile unsigned long _res;                                \
5273
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5274
      _argvec[1] = (unsigned long)(arg1);                         \
5275
      _argvec[2] = (unsigned long)(arg2);                         \
5276
      _argvec[3] = (unsigned long)(arg3);                         \
5277
      _argvec[4] = (unsigned long)(arg4);                         \
5278
      __asm__ volatile(                                           \
5279
         "subu $29, $29, 8 \n\t"                                  \
5280
         "sw $28, 0($29) \n\t"                                    \
5281
         "sw $31, 4($29) \n\t"                                    \
5282
         "subu $29, $29, 16 \n\t"                                 \
5283
         "lw $4, 4(%1) \n\t"                                      \
5284
         "lw $5, 8(%1) \n\t"                                      \
5285
         "lw $6, 12(%1) \n\t"                                     \
5286
         "lw $7, 16(%1) \n\t"                                     \
5287
         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5288
         VALGRIND_CALL_NOREDIR_T9                                 \
5289
         "addu $29, $29, 16 \n\t"                                 \
5290
         "lw $28, 0($29) \n\t"                                    \
5291
         "lw $31, 4($29) \n\t"                                    \
5292
         "addu $29, $29, 8 \n\t"                                  \
5293
         "move %0, $2\n"                                          \
5294
         : /*out*/   "=r" (_res)                                  \
5295
         : /*in*/    "0" (&_argvec[0])                            \
5296
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5297
      );                                                          \
5298
      lval = (__typeof__(lval)) _res;                             \
5299
   } while (0)
5300
5301
#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
5302
   do {                                                           \
5303
      volatile OrigFn        _orig = (orig);                      \
5304
      volatile unsigned long _argvec[6];                          \
5305
      volatile unsigned long _res;                                \
5306
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5307
      _argvec[1] = (unsigned long)(arg1);                         \
5308
      _argvec[2] = (unsigned long)(arg2);                         \
5309
      _argvec[3] = (unsigned long)(arg3);                         \
5310
      _argvec[4] = (unsigned long)(arg4);                         \
5311
      _argvec[5] = (unsigned long)(arg5);                         \
5312
      __asm__ volatile(                                           \
5313
         "subu $29, $29, 8 \n\t"                                  \
5314
         "sw $28, 0($29) \n\t"                                    \
5315
         "sw $31, 4($29) \n\t"                                    \
5316
         "lw $4, 20(%1) \n\t"                                     \
5317
         "subu $29, $29, 24\n\t"                                  \
5318
         "sw $4, 16($29) \n\t"                                    \
5319
         "lw $4, 4(%1) \n\t"                                      \
5320
         "lw $5, 8(%1) \n\t"                                      \
5321
         "lw $6, 12(%1) \n\t"                                     \
5322
         "lw $7, 16(%1) \n\t"                                     \
5323
         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5324
         VALGRIND_CALL_NOREDIR_T9                                 \
5325
         "addu $29, $29, 24 \n\t"                                 \
5326
         "lw $28, 0($29) \n\t"                                    \
5327
         "lw $31, 4($29) \n\t"                                    \
5328
         "addu $29, $29, 8 \n\t"                                  \
5329
         "move %0, $2\n"                                          \
5330
         : /*out*/   "=r" (_res)                                  \
5331
         : /*in*/    "0" (&_argvec[0])                            \
5332
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5333
      );                                                          \
5334
      lval = (__typeof__(lval)) _res;                             \
5335
   } while (0)
5336
#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
5337
   do {                                                           \
5338
      volatile OrigFn        _orig = (orig);                      \
5339
      volatile unsigned long _argvec[7];                          \
5340
      volatile unsigned long _res;                                \
5341
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5342
      _argvec[1] = (unsigned long)(arg1);                         \
5343
      _argvec[2] = (unsigned long)(arg2);                         \
5344
      _argvec[3] = (unsigned long)(arg3);                         \
5345
      _argvec[4] = (unsigned long)(arg4);                         \
5346
      _argvec[5] = (unsigned long)(arg5);                         \
5347
      _argvec[6] = (unsigned long)(arg6);                         \
5348
      __asm__ volatile(                                           \
5349
         "subu $29, $29, 8 \n\t"                                  \
5350
         "sw $28, 0($29) \n\t"                                    \
5351
         "sw $31, 4($29) \n\t"                                    \
5352
         "lw $4, 20(%1) \n\t"                                     \
5353
         "subu $29, $29, 32\n\t"                                  \
5354
         "sw $4, 16($29) \n\t"                                    \
5355
         "lw $4, 24(%1) \n\t"                                     \
5356
         "nop\n\t"                                                \
5357
         "sw $4, 20($29) \n\t"                                    \
5358
         "lw $4, 4(%1) \n\t"                                      \
5359
         "lw $5, 8(%1) \n\t"                                      \
5360
         "lw $6, 12(%1) \n\t"                                     \
5361
         "lw $7, 16(%1) \n\t"                                     \
5362
         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5363
         VALGRIND_CALL_NOREDIR_T9                                 \
5364
         "addu $29, $29, 32 \n\t"                                 \
5365
         "lw $28, 0($29) \n\t"                                    \
5366
         "lw $31, 4($29) \n\t"                                    \
5367
         "addu $29, $29, 8 \n\t"                                  \
5368
         "move %0, $2\n"                                          \
5369
         : /*out*/   "=r" (_res)                                  \
5370
         : /*in*/    "0" (&_argvec[0])                            \
5371
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5372
      );                                                          \
5373
      lval = (__typeof__(lval)) _res;                             \
5374
   } while (0)
5375
5376
#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
5377
                                 arg7)                            \
5378
   do {                                                           \
5379
      volatile OrigFn        _orig = (orig);                      \
5380
      volatile unsigned long _argvec[8];                          \
5381
      volatile unsigned long _res;                                \
5382
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5383
      _argvec[1] = (unsigned long)(arg1);                         \
5384
      _argvec[2] = (unsigned long)(arg2);                         \
5385
      _argvec[3] = (unsigned long)(arg3);                         \
5386
      _argvec[4] = (unsigned long)(arg4);                         \
5387
      _argvec[5] = (unsigned long)(arg5);                         \
5388
      _argvec[6] = (unsigned long)(arg6);                         \
5389
      _argvec[7] = (unsigned long)(arg7);                         \
5390
      __asm__ volatile(                                           \
5391
         "subu $29, $29, 8 \n\t"                                  \
5392
         "sw $28, 0($29) \n\t"                                    \
5393
         "sw $31, 4($29) \n\t"                                    \
5394
         "lw $4, 20(%1) \n\t"                                     \
5395
         "subu $29, $29, 32\n\t"                                  \
5396
         "sw $4, 16($29) \n\t"                                    \
5397
         "lw $4, 24(%1) \n\t"                                     \
5398
         "sw $4, 20($29) \n\t"                                    \
5399
         "lw $4, 28(%1) \n\t"                                     \
5400
         "sw $4, 24($29) \n\t"                                    \
5401
         "lw $4, 4(%1) \n\t"                                      \
5402
         "lw $5, 8(%1) \n\t"                                      \
5403
         "lw $6, 12(%1) \n\t"                                     \
5404
         "lw $7, 16(%1) \n\t"                                     \
5405
         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5406
         VALGRIND_CALL_NOREDIR_T9                                 \
5407
         "addu $29, $29, 32 \n\t"                                 \
5408
         "lw $28, 0($29) \n\t"                                    \
5409
         "lw $31, 4($29) \n\t"                                    \
5410
         "addu $29, $29, 8 \n\t"                                  \
5411
         "move %0, $2\n"                                          \
5412
         : /*out*/   "=r" (_res)                                  \
5413
         : /*in*/    "0" (&_argvec[0])                            \
5414
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5415
      );                                                          \
5416
      lval = (__typeof__(lval)) _res;                             \
5417
   } while (0)
5418
5419
#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
5420
                                 arg7,arg8)                       \
5421
   do {                                                           \
5422
      volatile OrigFn        _orig = (orig);                      \
5423
      volatile unsigned long _argvec[9];                          \
5424
      volatile unsigned long _res;                                \
5425
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5426
      _argvec[1] = (unsigned long)(arg1);                         \
5427
      _argvec[2] = (unsigned long)(arg2);                         \
5428
      _argvec[3] = (unsigned long)(arg3);                         \
5429
      _argvec[4] = (unsigned long)(arg4);                         \
5430
      _argvec[5] = (unsigned long)(arg5);                         \
5431
      _argvec[6] = (unsigned long)(arg6);                         \
5432
      _argvec[7] = (unsigned long)(arg7);                         \
5433
      _argvec[8] = (unsigned long)(arg8);                         \
5434
      __asm__ volatile(                                           \
5435
         "subu $29, $29, 8 \n\t"                                  \
5436
         "sw $28, 0($29) \n\t"                                    \
5437
         "sw $31, 4($29) \n\t"                                    \
5438
         "lw $4, 20(%1) \n\t"                                     \
5439
         "subu $29, $29, 40\n\t"                                  \
5440
         "sw $4, 16($29) \n\t"                                    \
5441
         "lw $4, 24(%1) \n\t"                                     \
5442
         "sw $4, 20($29) \n\t"                                    \
5443
         "lw $4, 28(%1) \n\t"                                     \
5444
         "sw $4, 24($29) \n\t"                                    \
5445
         "lw $4, 32(%1) \n\t"                                     \
5446
         "sw $4, 28($29) \n\t"                                    \
5447
         "lw $4, 4(%1) \n\t"                                      \
5448
         "lw $5, 8(%1) \n\t"                                      \
5449
         "lw $6, 12(%1) \n\t"                                     \
5450
         "lw $7, 16(%1) \n\t"                                     \
5451
         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5452
         VALGRIND_CALL_NOREDIR_T9                                 \
5453
         "addu $29, $29, 40 \n\t"                                 \
5454
         "lw $28, 0($29) \n\t"                                    \
5455
         "lw $31, 4($29) \n\t"                                    \
5456
         "addu $29, $29, 8 \n\t"                                  \
5457
         "move %0, $2\n"                                          \
5458
         : /*out*/   "=r" (_res)                                  \
5459
         : /*in*/    "0" (&_argvec[0])                            \
5460
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5461
      );                                                          \
5462
      lval = (__typeof__(lval)) _res;                             \
5463
   } while (0)
5464
5465
#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
5466
                                 arg7,arg8,arg9)                  \
5467
   do {                                                           \
5468
      volatile OrigFn        _orig = (orig);                      \
5469
      volatile unsigned long _argvec[10];                         \
5470
      volatile unsigned long _res;                                \
5471
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5472
      _argvec[1] = (unsigned long)(arg1);                         \
5473
      _argvec[2] = (unsigned long)(arg2);                         \
5474
      _argvec[3] = (unsigned long)(arg3);                         \
5475
      _argvec[4] = (unsigned long)(arg4);                         \
5476
      _argvec[5] = (unsigned long)(arg5);                         \
5477
      _argvec[6] = (unsigned long)(arg6);                         \
5478
      _argvec[7] = (unsigned long)(arg7);                         \
5479
      _argvec[8] = (unsigned long)(arg8);                         \
5480
      _argvec[9] = (unsigned long)(arg9);                         \
5481
      __asm__ volatile(                                           \
5482
         "subu $29, $29, 8 \n\t"                                  \
5483
         "sw $28, 0($29) \n\t"                                    \
5484
         "sw $31, 4($29) \n\t"                                    \
5485
         "lw $4, 20(%1) \n\t"                                     \
5486
         "subu $29, $29, 40\n\t"                                  \
5487
         "sw $4, 16($29) \n\t"                                    \
5488
         "lw $4, 24(%1) \n\t"                                     \
5489
         "sw $4, 20($29) \n\t"                                    \
5490
         "lw $4, 28(%1) \n\t"                                     \
5491
         "sw $4, 24($29) \n\t"                                    \
5492
         "lw $4, 32(%1) \n\t"                                     \
5493
         "sw $4, 28($29) \n\t"                                    \
5494
         "lw $4, 36(%1) \n\t"                                     \
5495
         "sw $4, 32($29) \n\t"                                    \
5496
         "lw $4, 4(%1) \n\t"                                      \
5497
         "lw $5, 8(%1) \n\t"                                      \
5498
         "lw $6, 12(%1) \n\t"                                     \
5499
         "lw $7, 16(%1) \n\t"                                     \
5500
         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5501
         VALGRIND_CALL_NOREDIR_T9                                 \
5502
         "addu $29, $29, 40 \n\t"                                 \
5503
         "lw $28, 0($29) \n\t"                                    \
5504
         "lw $31, 4($29) \n\t"                                    \
5505
         "addu $29, $29, 8 \n\t"                                  \
5506
         "move %0, $2\n"                                          \
5507
         : /*out*/   "=r" (_res)                                  \
5508
         : /*in*/    "0" (&_argvec[0])                            \
5509
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5510
      );                                                          \
5511
      lval = (__typeof__(lval)) _res;                             \
5512
   } while (0)
5513
5514
#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
5515
                                  arg7,arg8,arg9,arg10)           \
5516
   do {                                                           \
5517
      volatile OrigFn        _orig = (orig);                      \
5518
      volatile unsigned long _argvec[11];                         \
5519
      volatile unsigned long _res;                                \
5520
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5521
      _argvec[1] = (unsigned long)(arg1);                         \
5522
      _argvec[2] = (unsigned long)(arg2);                         \
5523
      _argvec[3] = (unsigned long)(arg3);                         \
5524
      _argvec[4] = (unsigned long)(arg4);                         \
5525
      _argvec[5] = (unsigned long)(arg5);                         \
5526
      _argvec[6] = (unsigned long)(arg6);                         \
5527
      _argvec[7] = (unsigned long)(arg7);                         \
5528
      _argvec[8] = (unsigned long)(arg8);                         \
5529
      _argvec[9] = (unsigned long)(arg9);                         \
5530
      _argvec[10] = (unsigned long)(arg10);                       \
5531
      __asm__ volatile(                                           \
5532
         "subu $29, $29, 8 \n\t"                                  \
5533
         "sw $28, 0($29) \n\t"                                    \
5534
         "sw $31, 4($29) \n\t"                                    \
5535
         "lw $4, 20(%1) \n\t"                                     \
5536
         "subu $29, $29, 48\n\t"                                  \
5537
         "sw $4, 16($29) \n\t"                                    \
5538
         "lw $4, 24(%1) \n\t"                                     \
5539
         "sw $4, 20($29) \n\t"                                    \
5540
         "lw $4, 28(%1) \n\t"                                     \
5541
         "sw $4, 24($29) \n\t"                                    \
5542
         "lw $4, 32(%1) \n\t"                                     \
5543
         "sw $4, 28($29) \n\t"                                    \
5544
         "lw $4, 36(%1) \n\t"                                     \
5545
         "sw $4, 32($29) \n\t"                                    \
5546
         "lw $4, 40(%1) \n\t"                                     \
5547
         "sw $4, 36($29) \n\t"                                    \
5548
         "lw $4, 4(%1) \n\t"                                      \
5549
         "lw $5, 8(%1) \n\t"                                      \
5550
         "lw $6, 12(%1) \n\t"                                     \
5551
         "lw $7, 16(%1) \n\t"                                     \
5552
         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5553
         VALGRIND_CALL_NOREDIR_T9                                 \
5554
         "addu $29, $29, 48 \n\t"                                 \
5555
         "lw $28, 0($29) \n\t"                                    \
5556
         "lw $31, 4($29) \n\t"                                    \
5557
         "addu $29, $29, 8 \n\t"                                  \
5558
         "move %0, $2\n"                                          \
5559
         : /*out*/   "=r" (_res)                                  \
5560
         : /*in*/    "0" (&_argvec[0])                            \
5561
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5562
      );                                                          \
5563
      lval = (__typeof__(lval)) _res;                             \
5564
   } while (0)
5565
5566
#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
5567
                                  arg6,arg7,arg8,arg9,arg10,      \
5568
                                  arg11)                          \
5569
   do {                                                           \
5570
      volatile OrigFn        _orig = (orig);                      \
5571
      volatile unsigned long _argvec[12];                         \
5572
      volatile unsigned long _res;                                \
5573
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5574
      _argvec[1] = (unsigned long)(arg1);                         \
5575
      _argvec[2] = (unsigned long)(arg2);                         \
5576
      _argvec[3] = (unsigned long)(arg3);                         \
5577
      _argvec[4] = (unsigned long)(arg4);                         \
5578
      _argvec[5] = (unsigned long)(arg5);                         \
5579
      _argvec[6] = (unsigned long)(arg6);                         \
5580
      _argvec[7] = (unsigned long)(arg7);                         \
5581
      _argvec[8] = (unsigned long)(arg8);                         \
5582
      _argvec[9] = (unsigned long)(arg9);                         \
5583
      _argvec[10] = (unsigned long)(arg10);                       \
5584
      _argvec[11] = (unsigned long)(arg11);                       \
5585
      __asm__ volatile(                                           \
5586
         "subu $29, $29, 8 \n\t"                                  \
5587
         "sw $28, 0($29) \n\t"                                    \
5588
         "sw $31, 4($29) \n\t"                                    \
5589
         "lw $4, 20(%1) \n\t"                                     \
5590
         "subu $29, $29, 48\n\t"                                  \
5591
         "sw $4, 16($29) \n\t"                                    \
5592
         "lw $4, 24(%1) \n\t"                                     \
5593
         "sw $4, 20($29) \n\t"                                    \
5594
         "lw $4, 28(%1) \n\t"                                     \
5595
         "sw $4, 24($29) \n\t"                                    \
5596
         "lw $4, 32(%1) \n\t"                                     \
5597
         "sw $4, 28($29) \n\t"                                    \
5598
         "lw $4, 36(%1) \n\t"                                     \
5599
         "sw $4, 32($29) \n\t"                                    \
5600
         "lw $4, 40(%1) \n\t"                                     \
5601
         "sw $4, 36($29) \n\t"                                    \
5602
         "lw $4, 44(%1) \n\t"                                     \
5603
         "sw $4, 40($29) \n\t"                                    \
5604
         "lw $4, 4(%1) \n\t"                                      \
5605
         "lw $5, 8(%1) \n\t"                                      \
5606
         "lw $6, 12(%1) \n\t"                                     \
5607
         "lw $7, 16(%1) \n\t"                                     \
5608
         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5609
         VALGRIND_CALL_NOREDIR_T9                                 \
5610
         "addu $29, $29, 48 \n\t"                                 \
5611
         "lw $28, 0($29) \n\t"                                    \
5612
         "lw $31, 4($29) \n\t"                                    \
5613
         "addu $29, $29, 8 \n\t"                                  \
5614
         "move %0, $2\n"                                          \
5615
         : /*out*/   "=r" (_res)                                  \
5616
         : /*in*/    "0" (&_argvec[0])                            \
5617
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5618
      );                                                          \
5619
      lval = (__typeof__(lval)) _res;                             \
5620
   } while (0)
5621
5622
#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
5623
                                  arg6,arg7,arg8,arg9,arg10,      \
5624
                                  arg11,arg12)                    \
5625
   do {                                                           \
5626
      volatile OrigFn        _orig = (orig);                      \
5627
      volatile unsigned long _argvec[13];                         \
5628
      volatile unsigned long _res;                                \
5629
      _argvec[0] = (unsigned long)_orig.nraddr;                   \
5630
      _argvec[1] = (unsigned long)(arg1);                         \
5631
      _argvec[2] = (unsigned long)(arg2);                         \
5632
      _argvec[3] = (unsigned long)(arg3);                         \
5633
      _argvec[4] = (unsigned long)(arg4);                         \
5634
      _argvec[5] = (unsigned long)(arg5);                         \
5635
      _argvec[6] = (unsigned long)(arg6);                         \
5636
      _argvec[7] = (unsigned long)(arg7);                         \
5637
      _argvec[8] = (unsigned long)(arg8);                         \
5638
      _argvec[9] = (unsigned long)(arg9);                         \
5639
      _argvec[10] = (unsigned long)(arg10);                       \
5640
      _argvec[11] = (unsigned long)(arg11);                       \
5641
      _argvec[12] = (unsigned long)(arg12);                       \
5642
      __asm__ volatile(                                           \
5643
         "subu $29, $29, 8 \n\t"                                  \
5644
         "sw $28, 0($29) \n\t"                                    \
5645
         "sw $31, 4($29) \n\t"                                    \
5646
         "lw $4, 20(%1) \n\t"                                     \
5647
         "subu $29, $29, 56\n\t"                                  \
5648
         "sw $4, 16($29) \n\t"                                    \
5649
         "lw $4, 24(%1) \n\t"                                     \
5650
         "sw $4, 20($29) \n\t"                                    \
5651
         "lw $4, 28(%1) \n\t"                                     \
5652
         "sw $4, 24($29) \n\t"                                    \
5653
         "lw $4, 32(%1) \n\t"                                     \
5654
         "sw $4, 28($29) \n\t"                                    \
5655
         "lw $4, 36(%1) \n\t"                                     \
5656
         "sw $4, 32($29) \n\t"                                    \
5657
         "lw $4, 40(%1) \n\t"                                     \
5658
         "sw $4, 36($29) \n\t"                                    \
5659
         "lw $4, 44(%1) \n\t"                                     \
5660
         "sw $4, 40($29) \n\t"                                    \
5661
         "lw $4, 48(%1) \n\t"                                     \
5662
         "sw $4, 44($29) \n\t"                                    \
5663
         "lw $4, 4(%1) \n\t"                                      \
5664
         "lw $5, 8(%1) \n\t"                                      \
5665
         "lw $6, 12(%1) \n\t"                                     \
5666
         "lw $7, 16(%1) \n\t"                                     \
5667
         "lw $25, 0(%1) \n\t"  /* target->t9 */                   \
5668
         VALGRIND_CALL_NOREDIR_T9                                 \
5669
         "addu $29, $29, 56 \n\t"                                 \
5670
         "lw $28, 0($29) \n\t"                                    \
5671
         "lw $31, 4($29) \n\t"                                    \
5672
         "addu $29, $29, 8 \n\t"                                  \
5673
         "move %0, $2\n"                                          \
5674
         : /*out*/   "=r" (_res)                                  \
5675
         : /*in*/    "r" (&_argvec[0])                            \
5676
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5677
      );                                                          \
5678
      lval = (__typeof__(lval)) _res;                             \
5679
   } while (0)
5680
5681
#endif /* PLAT_mips32_linux */
5682
5683
/* ------------------------- mips64-linux ------------------------- */
5684
5685
#if defined(PLAT_mips64_linux)
5686
5687
/* These regs are trashed by the hidden call. */
5688
#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6",       \
5689
"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
5690
"$25", "$31"
5691
5692
/* These CALL_FN_ macros assume that on mips64-linux,
5693
   sizeof(long long) == 8. */
5694
5695
#define MIPS64_LONG2REG_CAST(x) ((long long)(long)x)
5696
5697
#define CALL_FN_W_v(lval, orig)                                   \
5698
   do {                                                           \
5699
      volatile OrigFn        _orig = (orig);                      \
5700
      volatile unsigned long long _argvec[1];                     \
5701
      volatile unsigned long long _res;                           \
5702
      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5703
      __asm__ volatile(                                           \
5704
         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5705
         VALGRIND_CALL_NOREDIR_T9                                 \
5706
         "move %0, $2\n"                                          \
5707
         : /*out*/   "=r" (_res)                                  \
5708
         : /*in*/    "0" (&_argvec[0])                            \
5709
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5710
      );                                                          \
5711
      lval = (__typeof__(lval)) (long)_res;                       \
5712
   } while (0)
5713
5714
#define CALL_FN_W_W(lval, orig, arg1)                             \
5715
   do {                                                           \
5716
      volatile OrigFn        _orig = (orig);                      \
5717
      volatile unsigned long long _argvec[2];                     \
5718
      volatile unsigned long long  _res;                          \
5719
      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5720
      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5721
      __asm__ volatile(                                           \
5722
         "ld $4, 8(%1)\n\t"   /* arg1*/                           \
5723
         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5724
         VALGRIND_CALL_NOREDIR_T9                                 \
5725
         "move %0, $2\n"                                          \
5726
         : /*out*/   "=r" (_res)                                  \
5727
         : /*in*/    "r" (&_argvec[0])                            \
5728
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5729
      );                                                          \
5730
      lval = (__typeof__(lval)) (long)_res;                       \
5731
   } while (0)
5732
5733
#define CALL_FN_W_WW(lval, orig, arg1,arg2)                       \
5734
   do {                                                           \
5735
      volatile OrigFn        _orig = (orig);                      \
5736
      volatile unsigned long long _argvec[3];                     \
5737
      volatile unsigned long long _res;                           \
5738
      _argvec[0] = _orig.nraddr;                                  \
5739
      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5740
      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5741
      __asm__ volatile(                                           \
5742
         "ld $4, 8(%1)\n\t"                                       \
5743
         "ld $5, 16(%1)\n\t"                                      \
5744
         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5745
         VALGRIND_CALL_NOREDIR_T9                                 \
5746
         "move %0, $2\n"                                          \
5747
         : /*out*/   "=r" (_res)                                  \
5748
         : /*in*/    "r" (&_argvec[0])                            \
5749
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5750
      );                                                          \
5751
      lval = (__typeof__(lval)) (long)_res;                       \
5752
   } while (0)
5753
5754
5755
#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3)                 \
5756
   do {                                                           \
5757
      volatile OrigFn        _orig = (orig);                      \
5758
      volatile unsigned long long _argvec[4];                     \
5759
      volatile unsigned long long _res;                           \
5760
      _argvec[0] = _orig.nraddr;                                  \
5761
      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5762
      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5763
      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
5764
      __asm__ volatile(                                           \
5765
         "ld $4, 8(%1)\n\t"                                       \
5766
         "ld $5, 16(%1)\n\t"                                      \
5767
         "ld $6, 24(%1)\n\t"                                      \
5768
         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5769
         VALGRIND_CALL_NOREDIR_T9                                 \
5770
         "move %0, $2\n"                                          \
5771
         : /*out*/   "=r" (_res)                                  \
5772
         : /*in*/    "r" (&_argvec[0])                            \
5773
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5774
      );                                                          \
5775
      lval = (__typeof__(lval)) (long)_res;                       \
5776
   } while (0)
5777
5778
#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4)           \
5779
   do {                                                           \
5780
      volatile OrigFn        _orig = (orig);                      \
5781
      volatile unsigned long long _argvec[5];                     \
5782
      volatile unsigned long long _res;                           \
5783
      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5784
      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5785
      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5786
      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
5787
      _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
5788
      __asm__ volatile(                                           \
5789
         "ld $4, 8(%1)\n\t"                                       \
5790
         "ld $5, 16(%1)\n\t"                                      \
5791
         "ld $6, 24(%1)\n\t"                                      \
5792
         "ld $7, 32(%1)\n\t"                                      \
5793
         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5794
         VALGRIND_CALL_NOREDIR_T9                                 \
5795
         "move %0, $2\n"                                          \
5796
         : /*out*/   "=r" (_res)                                  \
5797
         : /*in*/    "r" (&_argvec[0])                            \
5798
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5799
      );                                                          \
5800
      lval = (__typeof__(lval)) (long)_res;                       \
5801
   } while (0)
5802
5803
#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5)        \
5804
   do {                                                           \
5805
      volatile OrigFn        _orig = (orig);                      \
5806
      volatile unsigned long long _argvec[6];                     \
5807
      volatile unsigned long long _res;                           \
5808
      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5809
      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5810
      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5811
      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
5812
      _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
5813
      _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
5814
      __asm__ volatile(                                           \
5815
         "ld $4, 8(%1)\n\t"                                       \
5816
         "ld $5, 16(%1)\n\t"                                      \
5817
         "ld $6, 24(%1)\n\t"                                      \
5818
         "ld $7, 32(%1)\n\t"                                      \
5819
         "ld $8, 40(%1)\n\t"                                      \
5820
         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5821
         VALGRIND_CALL_NOREDIR_T9                                 \
5822
         "move %0, $2\n"                                          \
5823
         : /*out*/   "=r" (_res)                                  \
5824
         : /*in*/    "r" (&_argvec[0])                            \
5825
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5826
      );                                                          \
5827
      lval = (__typeof__(lval)) (long)_res;                       \
5828
   } while (0)
5829
5830
#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6)   \
5831
   do {                                                           \
5832
      volatile OrigFn        _orig = (orig);                      \
5833
      volatile unsigned long long _argvec[7];                     \
5834
      volatile unsigned long long _res;                           \
5835
      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5836
      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5837
      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5838
      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
5839
      _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
5840
      _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
5841
      _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
5842
      __asm__ volatile(                                           \
5843
         "ld $4, 8(%1)\n\t"                                       \
5844
         "ld $5, 16(%1)\n\t"                                      \
5845
         "ld $6, 24(%1)\n\t"                                      \
5846
         "ld $7, 32(%1)\n\t"                                      \
5847
         "ld $8, 40(%1)\n\t"                                      \
5848
         "ld $9, 48(%1)\n\t"                                      \
5849
         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5850
         VALGRIND_CALL_NOREDIR_T9                                 \
5851
         "move %0, $2\n"                                          \
5852
         : /*out*/   "=r" (_res)                                  \
5853
         : /*in*/    "r" (&_argvec[0])                            \
5854
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5855
      );                                                          \
5856
      lval = (__typeof__(lval)) (long)_res;                       \
5857
   } while (0)
5858
5859
#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
5860
                                 arg7)                            \
5861
   do {                                                           \
5862
      volatile OrigFn        _orig = (orig);                      \
5863
      volatile unsigned long long _argvec[8];                     \
5864
      volatile unsigned long long _res;                           \
5865
      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5866
      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5867
      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5868
      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
5869
      _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
5870
      _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
5871
      _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
5872
      _argvec[7] = MIPS64_LONG2REG_CAST(arg7);                    \
5873
      __asm__ volatile(                                           \
5874
         "ld $4, 8(%1)\n\t"                                       \
5875
         "ld $5, 16(%1)\n\t"                                      \
5876
         "ld $6, 24(%1)\n\t"                                      \
5877
         "ld $7, 32(%1)\n\t"                                      \
5878
         "ld $8, 40(%1)\n\t"                                      \
5879
         "ld $9, 48(%1)\n\t"                                      \
5880
         "ld $10, 56(%1)\n\t"                                     \
5881
         "ld $25, 0(%1) \n\t"  /* target->t9 */                   \
5882
         VALGRIND_CALL_NOREDIR_T9                                 \
5883
         "move %0, $2\n"                                          \
5884
         : /*out*/   "=r" (_res)                                  \
5885
         : /*in*/    "r" (&_argvec[0])                            \
5886
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5887
      );                                                          \
5888
      lval = (__typeof__(lval)) (long)_res;                       \
5889
   } while (0)
5890
5891
#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
5892
                                 arg7,arg8)                       \
5893
   do {                                                           \
5894
      volatile OrigFn        _orig = (orig);                      \
5895
      volatile unsigned long long _argvec[9];                     \
5896
      volatile unsigned long long _res;                           \
5897
      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5898
      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5899
      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5900
      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
5901
      _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
5902
      _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
5903
      _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
5904
      _argvec[7] = MIPS64_LONG2REG_CAST(arg7);                    \
5905
      _argvec[8] = MIPS64_LONG2REG_CAST(arg8);                    \
5906
      __asm__ volatile(                                           \
5907
         "ld $4, 8(%1)\n\t"                                       \
5908
         "ld $5, 16(%1)\n\t"                                      \
5909
         "ld $6, 24(%1)\n\t"                                      \
5910
         "ld $7, 32(%1)\n\t"                                      \
5911
         "ld $8, 40(%1)\n\t"                                      \
5912
         "ld $9, 48(%1)\n\t"                                      \
5913
         "ld $10, 56(%1)\n\t"                                     \
5914
         "ld $11, 64(%1)\n\t"                                     \
5915
         "ld $25, 0(%1) \n\t"  /* target->t9 */                   \
5916
         VALGRIND_CALL_NOREDIR_T9                                 \
5917
         "move %0, $2\n"                                          \
5918
         : /*out*/   "=r" (_res)                                  \
5919
         : /*in*/    "r" (&_argvec[0])                            \
5920
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5921
      );                                                          \
5922
      lval = (__typeof__(lval)) (long)_res;                       \
5923
   } while (0)
5924
5925
#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,   \
5926
                                 arg7,arg8,arg9)                  \
5927
   do {                                                           \
5928
      volatile OrigFn        _orig = (orig);                      \
5929
      volatile unsigned long long _argvec[10];                    \
5930
      volatile unsigned long long _res;                           \
5931
      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5932
      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5933
      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5934
      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
5935
      _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
5936
      _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
5937
      _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
5938
      _argvec[7] = MIPS64_LONG2REG_CAST(arg7);                    \
5939
      _argvec[8] = MIPS64_LONG2REG_CAST(arg8);                    \
5940
      _argvec[9] = MIPS64_LONG2REG_CAST(arg9);                    \
5941
      __asm__ volatile(                                           \
5942
         "dsubu $29, $29, 8\n\t"                                  \
5943
         "ld $4, 72(%1)\n\t"                                      \
5944
         "sd $4, 0($29)\n\t"                                      \
5945
         "ld $4, 8(%1)\n\t"                                       \
5946
         "ld $5, 16(%1)\n\t"                                      \
5947
         "ld $6, 24(%1)\n\t"                                      \
5948
         "ld $7, 32(%1)\n\t"                                      \
5949
         "ld $8, 40(%1)\n\t"                                      \
5950
         "ld $9, 48(%1)\n\t"                                      \
5951
         "ld $10, 56(%1)\n\t"                                     \
5952
         "ld $11, 64(%1)\n\t"                                     \
5953
         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5954
         VALGRIND_CALL_NOREDIR_T9                                 \
5955
         "daddu $29, $29, 8\n\t"                                  \
5956
         "move %0, $2\n"                                          \
5957
         : /*out*/   "=r" (_res)                                  \
5958
         : /*in*/    "r" (&_argvec[0])                            \
5959
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
5960
      );                                                          \
5961
      lval = (__typeof__(lval)) (long)_res;                       \
5962
   } while (0)
5963
5964
#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6,  \
5965
                                  arg7,arg8,arg9,arg10)           \
5966
   do {                                                           \
5967
      volatile OrigFn        _orig = (orig);                      \
5968
      volatile unsigned long long _argvec[11];                    \
5969
      volatile unsigned long long _res;                           \
5970
      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
5971
      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
5972
      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
5973
      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
5974
      _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
5975
      _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
5976
      _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
5977
      _argvec[7] = MIPS64_LONG2REG_CAST(arg7);                    \
5978
      _argvec[8] = MIPS64_LONG2REG_CAST(arg8);                    \
5979
      _argvec[9] = MIPS64_LONG2REG_CAST(arg9);                    \
5980
      _argvec[10] = MIPS64_LONG2REG_CAST(arg10);                  \
5981
      __asm__ volatile(                                           \
5982
         "dsubu $29, $29, 16\n\t"                                 \
5983
         "ld $4, 72(%1)\n\t"                                      \
5984
         "sd $4, 0($29)\n\t"                                      \
5985
         "ld $4, 80(%1)\n\t"                                      \
5986
         "sd $4, 8($29)\n\t"                                      \
5987
         "ld $4, 8(%1)\n\t"                                       \
5988
         "ld $5, 16(%1)\n\t"                                      \
5989
         "ld $6, 24(%1)\n\t"                                      \
5990
         "ld $7, 32(%1)\n\t"                                      \
5991
         "ld $8, 40(%1)\n\t"                                      \
5992
         "ld $9, 48(%1)\n\t"                                      \
5993
         "ld $10, 56(%1)\n\t"                                     \
5994
         "ld $11, 64(%1)\n\t"                                     \
5995
         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
5996
         VALGRIND_CALL_NOREDIR_T9                                 \
5997
         "daddu $29, $29, 16\n\t"                                 \
5998
         "move %0, $2\n"                                          \
5999
         : /*out*/   "=r" (_res)                                  \
6000
         : /*in*/    "r" (&_argvec[0])                            \
6001
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6002
      );                                                          \
6003
      lval = (__typeof__(lval)) (long)_res;                       \
6004
   } while (0)
6005
6006
#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
6007
                                  arg6,arg7,arg8,arg9,arg10,      \
6008
                                  arg11)                          \
6009
   do {                                                           \
6010
      volatile OrigFn        _orig = (orig);                      \
6011
      volatile unsigned long long _argvec[12];                    \
6012
      volatile unsigned long long _res;                           \
6013
      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
6014
      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
6015
      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
6016
      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
6017
      _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
6018
      _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
6019
      _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
6020
      _argvec[7] = MIPS64_LONG2REG_CAST(arg7);                    \
6021
      _argvec[8] = MIPS64_LONG2REG_CAST(arg8);                    \
6022
      _argvec[9] = MIPS64_LONG2REG_CAST(arg9);                    \
6023
      _argvec[10] = MIPS64_LONG2REG_CAST(arg10);                  \
6024
      _argvec[11] = MIPS64_LONG2REG_CAST(arg11);                  \
6025
      __asm__ volatile(                                           \
6026
         "dsubu $29, $29, 24\n\t"                                 \
6027
         "ld $4, 72(%1)\n\t"                                      \
6028
         "sd $4, 0($29)\n\t"                                      \
6029
         "ld $4, 80(%1)\n\t"                                      \
6030
         "sd $4, 8($29)\n\t"                                      \
6031
         "ld $4, 88(%1)\n\t"                                      \
6032
         "sd $4, 16($29)\n\t"                                     \
6033
         "ld $4, 8(%1)\n\t"                                       \
6034
         "ld $5, 16(%1)\n\t"                                      \
6035
         "ld $6, 24(%1)\n\t"                                      \
6036
         "ld $7, 32(%1)\n\t"                                      \
6037
         "ld $8, 40(%1)\n\t"                                      \
6038
         "ld $9, 48(%1)\n\t"                                      \
6039
         "ld $10, 56(%1)\n\t"                                     \
6040
         "ld $11, 64(%1)\n\t"                                     \
6041
         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
6042
         VALGRIND_CALL_NOREDIR_T9                                 \
6043
         "daddu $29, $29, 24\n\t"                                 \
6044
         "move %0, $2\n"                                          \
6045
         : /*out*/   "=r" (_res)                                  \
6046
         : /*in*/    "r" (&_argvec[0])                            \
6047
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6048
      );                                                          \
6049
      lval = (__typeof__(lval)) (long)_res;                       \
6050
   } while (0)
6051
6052
#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,       \
6053
                                  arg6,arg7,arg8,arg9,arg10,      \
6054
                                  arg11,arg12)                    \
6055
   do {                                                           \
6056
      volatile OrigFn        _orig = (orig);                      \
6057
      volatile unsigned long long _argvec[13];                    \
6058
      volatile unsigned long long _res;                           \
6059
      _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr);            \
6060
      _argvec[1] = MIPS64_LONG2REG_CAST(arg1);                    \
6061
      _argvec[2] = MIPS64_LONG2REG_CAST(arg2);                    \
6062
      _argvec[3] = MIPS64_LONG2REG_CAST(arg3);                    \
6063
      _argvec[4] = MIPS64_LONG2REG_CAST(arg4);                    \
6064
      _argvec[5] = MIPS64_LONG2REG_CAST(arg5);                    \
6065
      _argvec[6] = MIPS64_LONG2REG_CAST(arg6);                    \
6066
      _argvec[7] = MIPS64_LONG2REG_CAST(arg7);                    \
6067
      _argvec[8] = MIPS64_LONG2REG_CAST(arg8);                    \
6068
      _argvec[9] = MIPS64_LONG2REG_CAST(arg9);                    \
6069
      _argvec[10] = MIPS64_LONG2REG_CAST(arg10);                  \
6070
      _argvec[11] = MIPS64_LONG2REG_CAST(arg11);                  \
6071
      _argvec[12] = MIPS64_LONG2REG_CAST(arg12);                  \
6072
      __asm__ volatile(                                           \
6073
         "dsubu $29, $29, 32\n\t"                                 \
6074
         "ld $4, 72(%1)\n\t"                                      \
6075
         "sd $4, 0($29)\n\t"                                      \
6076
         "ld $4, 80(%1)\n\t"                                      \
6077
         "sd $4, 8($29)\n\t"                                      \
6078
         "ld $4, 88(%1)\n\t"                                      \
6079
         "sd $4, 16($29)\n\t"                                     \
6080
         "ld $4, 96(%1)\n\t"                                      \
6081
         "sd $4, 24($29)\n\t"                                     \
6082
         "ld $4, 8(%1)\n\t"                                       \
6083
         "ld $5, 16(%1)\n\t"                                      \
6084
         "ld $6, 24(%1)\n\t"                                      \
6085
         "ld $7, 32(%1)\n\t"                                      \
6086
         "ld $8, 40(%1)\n\t"                                      \
6087
         "ld $9, 48(%1)\n\t"                                      \
6088
         "ld $10, 56(%1)\n\t"                                     \
6089
         "ld $11, 64(%1)\n\t"                                     \
6090
         "ld $25, 0(%1)\n\t"  /* target->t9 */                    \
6091
         VALGRIND_CALL_NOREDIR_T9                                 \
6092
         "daddu $29, $29, 32\n\t"                                 \
6093
         "move %0, $2\n"                                          \
6094
         : /*out*/   "=r" (_res)                                  \
6095
         : /*in*/    "r" (&_argvec[0])                            \
6096
         : /*trash*/ "memory", __CALLER_SAVED_REGS                \
6097
      );                                                          \
6098
      lval = (__typeof__(lval)) (long)_res;                       \
6099
   } while (0)
6100
6101
#endif /* PLAT_mips64_linux */
6102
6103
/* ------------------------------------------------------------------ */
6104
/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS.               */
6105
/*                                                                    */
6106
/* ------------------------------------------------------------------ */
6107
6108
/* Some request codes.  There are many more of these, but most are not
6109
   exposed to end-user view.  These are the public ones, all of the
6110
   form 0x1000 + small_number.
6111
6112
   Core ones are in the range 0x00000000--0x0000ffff.  The non-public
6113
   ones start at 0x2000.
6114
*/
6115
6116
/* These macros are used by tools -- they must be public, but don't
6117
   embed them into other programs. */
6118
#define VG_USERREQ_TOOL_BASE(a,b) \
6119
   ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
6120
#define VG_IS_TOOL_USERREQ(a, b, v) \
6121
   (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
6122
6123
/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! 
6124
   This enum comprises an ABI exported by Valgrind to programs
6125
   which use client requests.  DO NOT CHANGE THE NUMERIC VALUES OF THESE
6126
   ENTRIES, NOR DELETE ANY -- add new ones at the end of the most
6127
   relevant group. */
6128
typedef
6129
   enum { VG_USERREQ__RUNNING_ON_VALGRIND  = 0x1001,
6130
          VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
6131
6132
          /* These allow any function to be called from the simulated
6133
             CPU but run on the real CPU.  Nb: the first arg passed to
6134
             the function is always the ThreadId of the running
6135
             thread!  So CLIENT_CALL0 actually requires a 1 arg
6136
             function, etc. */
6137
          VG_USERREQ__CLIENT_CALL0 = 0x1101,
6138
          VG_USERREQ__CLIENT_CALL1 = 0x1102,
6139
          VG_USERREQ__CLIENT_CALL2 = 0x1103,
6140
          VG_USERREQ__CLIENT_CALL3 = 0x1104,
6141
6142
          /* Can be useful in regression testing suites -- eg. can
6143
             send Valgrind's output to /dev/null and still count
6144
             errors. */
6145
          VG_USERREQ__COUNT_ERRORS = 0x1201,
6146
6147
          /* Allows the client program and/or gdbserver to execute a monitor
6148
             command. */
6149
          VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
6150
6151
          /* These are useful and can be interpreted by any tool that
6152
             tracks malloc() et al, by using vg_replace_malloc.c. */
6153
          VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
6154
          VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
6155
          VG_USERREQ__FREELIKE_BLOCK   = 0x1302,
6156
          /* Memory pool support. */
6157
          VG_USERREQ__CREATE_MEMPOOL   = 0x1303,
6158
          VG_USERREQ__DESTROY_MEMPOOL  = 0x1304,
6159
          VG_USERREQ__MEMPOOL_ALLOC    = 0x1305,
6160
          VG_USERREQ__MEMPOOL_FREE     = 0x1306,
6161
          VG_USERREQ__MEMPOOL_TRIM     = 0x1307,
6162
          VG_USERREQ__MOVE_MEMPOOL     = 0x1308,
6163
          VG_USERREQ__MEMPOOL_CHANGE   = 0x1309,
6164
          VG_USERREQ__MEMPOOL_EXISTS   = 0x130a,
6165
6166
          /* Allow printfs to valgrind log. */
6167
          /* The first two pass the va_list argument by value, which
6168
             assumes it is the same size as or smaller than a UWord,
6169
             which generally isn't the case.  Hence are deprecated.
6170
             The second two pass the vargs by reference and so are
6171
             immune to this problem. */
6172
          /* both :: char* fmt, va_list vargs (DEPRECATED) */
6173
          VG_USERREQ__PRINTF           = 0x1401,
6174
          VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
6175
          /* both :: char* fmt, va_list* vargs */
6176
          VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
6177
          VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
6178
6179
          /* Stack support. */
6180
          VG_USERREQ__STACK_REGISTER   = 0x1501,
6181
          VG_USERREQ__STACK_DEREGISTER = 0x1502,
6182
          VG_USERREQ__STACK_CHANGE     = 0x1503,
6183
6184
          /* Wine support */
6185
          VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
6186
6187
          /* Querying of debug info. */
6188
          VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
6189
6190
          /* Disable/enable error reporting level.  Takes a single
6191
             Word arg which is the delta to this thread's error
6192
             disablement indicator.  Hence 1 disables or further
6193
             disables errors, and -1 moves back towards enablement.
6194
             Other values are not allowed. */
6195
          VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801,
6196
6197
          /* Some requests used for Valgrind internal, such as
6198
             self-test or self-hosting. */
6199
          /* Initialise IR injection */
6200
          VG_USERREQ__VEX_INIT_FOR_IRI = 0x1901,
6201
          /* Used by Inner Valgrind to inform Outer Valgrind where to
6202
             find the list of inner guest threads */
6203
          VG_USERREQ__INNER_THREADS    = 0x1902
6204
   } Vg_ClientRequest;
6205
6206
#if !defined(__GNUC__)
6207
#  define __extension__ /* */
6208
#endif
6209
6210
6211
/* Returns the number of Valgrinds this code is running under.  That
6212
   is, 0 if running natively, 1 if running under Valgrind, 2 if
6213
   running under Valgrind which is running under another Valgrind,
6214
   etc. */
6215
#define RUNNING_ON_VALGRIND                                           \
6216
70
    (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */,         \
6217
70
                                    VG_USERREQ__RUNNING_ON_VALGRIND,  \
6218
70
                                    0, 0, 0, 0, 0)                    \
6219
6220
6221
/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
6222
   _qzz_len - 1].  Useful if you are debugging a JITter or some such,
6223
   since it provides a way to make sure valgrind will retranslate the
6224
   invalidated area.  Returns no value. */
6225
#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len)              \
6226
    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DISCARD_TRANSLATIONS,  \
6227
                                    _qzz_addr, _qzz_len, 0, 0, 0)
6228
6229
#define VALGRIND_INNER_THREADS(_qzz_addr)                               \
6230
   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__INNER_THREADS,           \
6231
                                   _qzz_addr, 0, 0, 0, 0)
6232
6233
6234
/* These requests are for getting Valgrind itself to print something.
6235
   Possibly with a backtrace.  This is a really ugly hack.  The return value
6236
   is the number of characters printed, excluding the "**<pid>** " part at the
6237
   start and the backtrace (if present). */
6238
6239
#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
6240
/* Modern GCC will optimize the static routine out if unused,
6241
   and unused attribute will shut down warnings about it.  */
6242
static int VALGRIND_PRINTF(const char *format, ...)
6243
   __attribute__((format(__printf__, 1, 2), __unused__));
6244
#endif
6245
static int
6246
#if defined(_MSC_VER)
6247
__inline
6248
#endif
6249
VALGRIND_PRINTF(const char *format, ...)
6250
0
{
6251
0
#if defined(NVALGRIND)
6252
0
   (void)format;
6253
0
   return 0;
6254
0
#else /* NVALGRIND */
6255
0
#if defined(_MSC_VER) || defined(__MINGW64__)
6256
0
   uintptr_t _qzz_res;
6257
0
#else
6258
0
   unsigned long _qzz_res;
6259
0
#endif
6260
0
   va_list vargs;
6261
0
   va_start(vargs, format);
6262
0
#if defined(_MSC_VER) || defined(__MINGW64__)
6263
0
   _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
6264
0
                              VG_USERREQ__PRINTF_VALIST_BY_REF,
6265
0
                              (uintptr_t)format,
6266
0
                              (uintptr_t)&vargs,
6267
0
                              0, 0, 0);
6268
0
#else
6269
0
   _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
6270
0
                              VG_USERREQ__PRINTF_VALIST_BY_REF,
6271
0
                              (unsigned long)format,
6272
0
                              (unsigned long)&vargs, 
6273
0
                              0, 0, 0);
6274
0
#endif
6275
0
   va_end(vargs);
6276
0
   return (int)_qzz_res;
6277
0
#endif /* NVALGRIND */
6278
0
}
Unexecuted instantiation: gclosure.c:VALGRIND_PRINTF
Unexecuted instantiation: gtype.c:VALGRIND_PRINTF
Unexecuted instantiation: gatomicarray.c:VALGRIND_PRINTF
Unexecuted instantiation: gerror.c:VALGRIND_PRINTF
Unexecuted instantiation: ghash.c:VALGRIND_PRINTF
Unexecuted instantiation: gutf8.c:VALGRIND_PRINTF
6279
6280
#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
6281
static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
6282
   __attribute__((format(__printf__, 1, 2), __unused__));
6283
#endif
6284
static int
6285
#if defined(_MSC_VER)
6286
__inline
6287
#endif
6288
VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
6289
0
{
6290
0
#if defined(NVALGRIND)
6291
0
   (void)format;
6292
0
   return 0;
6293
0
#else /* NVALGRIND */
6294
0
#if defined(_MSC_VER) || defined(__MINGW64__)
6295
0
   uintptr_t _qzz_res;
6296
0
#else
6297
0
   unsigned long _qzz_res;
6298
0
#endif
6299
0
   va_list vargs;
6300
0
   va_start(vargs, format);
6301
0
#if defined(_MSC_VER) || defined(__MINGW64__)
6302
0
   _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
6303
0
                              VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
6304
0
                              (uintptr_t)format,
6305
0
                              (uintptr_t)&vargs,
6306
0
                              0, 0, 0);
6307
0
#else
6308
0
   _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
6309
0
                              VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
6310
0
                              (unsigned long)format,
6311
0
                              (unsigned long)&vargs, 
6312
0
                              0, 0, 0);
6313
0
#endif
6314
0
   va_end(vargs);
6315
0
   return (int)_qzz_res;
6316
0
#endif /* NVALGRIND */
6317
0
}
Unexecuted instantiation: gclosure.c:VALGRIND_PRINTF_BACKTRACE
Unexecuted instantiation: gtype.c:VALGRIND_PRINTF_BACKTRACE
Unexecuted instantiation: gatomicarray.c:VALGRIND_PRINTF_BACKTRACE
Unexecuted instantiation: gerror.c:VALGRIND_PRINTF_BACKTRACE
Unexecuted instantiation: ghash.c:VALGRIND_PRINTF_BACKTRACE
Unexecuted instantiation: gutf8.c:VALGRIND_PRINTF_BACKTRACE
6318
6319
6320
/* These requests allow control to move from the simulated CPU to the
6321
   real CPU, calling an arbitrary function.
6322
   
6323
   Note that the current ThreadId is inserted as the first argument.
6324
   So this call:
6325
6326
     VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
6327
6328
   requires f to have this signature:
6329
6330
     Word f(Word tid, Word arg1, Word arg2)
6331
6332
   where "Word" is a word-sized type.
6333
6334
   Note that these client requests are not entirely reliable.  For example,
6335
   if you call a function with them that subsequently calls printf(),
6336
   there's a high chance Valgrind will crash.  Generally, your prospects of
6337
   these working are made higher if the called function does not refer to
6338
   any global variables, and does not refer to any libc or other functions
6339
   (printf et al).  Any kind of entanglement with libc or dynamic linking is
6340
   likely to have a bad outcome, for tricky reasons which we've grappled
6341
   with a lot in the past.
6342
*/
6343
#define VALGRIND_NON_SIMD_CALL0(_qyy_fn)                          \
6344
    VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */,       \
6345
                                    VG_USERREQ__CLIENT_CALL0,     \
6346
                                    _qyy_fn,                      \
6347
                                    0, 0, 0, 0)
6348
6349
#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1)                    \
6350
    VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */,            \
6351
                                    VG_USERREQ__CLIENT_CALL1,          \
6352
                                    _qyy_fn,                           \
6353
                                    _qyy_arg1, 0, 0, 0)
6354
6355
#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2)         \
6356
    VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */,            \
6357
                                    VG_USERREQ__CLIENT_CALL2,          \
6358
                                    _qyy_fn,                           \
6359
                                    _qyy_arg1, _qyy_arg2, 0, 0)
6360
6361
#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
6362
    VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */,             \
6363
                                    VG_USERREQ__CLIENT_CALL3,           \
6364
                                    _qyy_fn,                            \
6365
                                    _qyy_arg1, _qyy_arg2,               \
6366
                                    _qyy_arg3, 0)
6367
6368
6369
/* Counts the number of errors that have been recorded by a tool.  Nb:
6370
   the tool must record the errors with VG_(maybe_record_error)() or
6371
   VG_(unique_error)() for them to be counted. */
6372
#define VALGRIND_COUNT_ERRORS                                     \
6373
    (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(                    \
6374
                               0 /* default return */,            \
6375
                               VG_USERREQ__COUNT_ERRORS,          \
6376
                               0, 0, 0, 0, 0)
6377
6378
/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
6379
   when heap blocks are allocated in order to give accurate results.  This
6380
   happens automatically for the standard allocator functions such as
6381
   malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
6382
   delete[], etc.
6383
6384
   But if your program uses a custom allocator, this doesn't automatically
6385
   happen, and Valgrind will not do as well.  For example, if you allocate
6386
   superblocks with mmap() and then allocates chunks of the superblocks, all
6387
   Valgrind's observations will be at the mmap() level and it won't know that
6388
   the chunks should be considered separate entities.  In Memcheck's case,
6389
   that means you probably won't get heap block overrun detection (because
6390
   there won't be redzones marked as unaddressable) and you definitely won't
6391
   get any leak detection.
6392
6393
   The following client requests allow a custom allocator to be annotated so
6394
   that it can be handled accurately by Valgrind.
6395
6396
   VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
6397
   by a malloc()-like function.  For Memcheck (an illustrative case), this
6398
   does two things:
6399
6400
   - It records that the block has been allocated.  This means any addresses
6401
     within the block mentioned in error messages will be
6402
     identified as belonging to the block.  It also means that if the block
6403
     isn't freed it will be detected by the leak checker.
6404
6405
   - It marks the block as being addressable and undefined (if 'is_zeroed' is
6406
     not set), or addressable and defined (if 'is_zeroed' is set).  This
6407
     controls how accesses to the block by the program are handled.
6408
   
6409
   'addr' is the start of the usable block (ie. after any
6410
   redzone), 'sizeB' is its size.  'rzB' is the redzone size if the allocator
6411
   can apply redzones -- these are blocks of padding at the start and end of
6412
   each block.  Adding redzones is recommended as it makes it much more likely
6413
   Valgrind will spot block overruns.  `is_zeroed' indicates if the memory is
6414
   zeroed (or filled with another predictable value), as is the case for
6415
   calloc().
6416
   
6417
   VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
6418
   heap block -- that will be used by the client program -- is allocated.
6419
   It's best to put it at the outermost level of the allocator if possible;
6420
   for example, if you have a function my_alloc() which calls
6421
   internal_alloc(), and the client request is put inside internal_alloc(),
6422
   stack traces relating to the heap block will contain entries for both
6423
   my_alloc() and internal_alloc(), which is probably not what you want.
6424
6425
   For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
6426
   custom blocks from within a heap block, B, that has been allocated with
6427
   malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
6428
   -- the custom blocks will take precedence.
6429
6430
   VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK.  For
6431
   Memcheck, it does two things:
6432
6433
   - It records that the block has been deallocated.  This assumes that the
6434
     block was annotated as having been allocated via
6435
     VALGRIND_MALLOCLIKE_BLOCK.  Otherwise, an error will be issued.
6436
6437
   - It marks the block as being unaddressable.
6438
6439
   VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
6440
   heap block is deallocated.
6441
6442
   VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For
6443
   Memcheck, it does four things:
6444
6445
   - It records that the size of a block has been changed.  This assumes that
6446
     the block was annotated as having been allocated via
6447
     VALGRIND_MALLOCLIKE_BLOCK.  Otherwise, an error will be issued.
6448
6449
   - If the block shrunk, it marks the freed memory as being unaddressable.
6450
6451
   - If the block grew, it marks the new area as undefined and defines a red
6452
     zone past the end of the new block.
6453
6454
   - The V-bits of the overlap between the old and the new block are preserved.
6455
6456
   VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block
6457
   and before deallocation of the old block.
6458
6459
   In many cases, these three client requests will not be enough to get your
6460
   allocator working well with Memcheck.  More specifically, if your allocator
6461
   writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
6462
   will be necessary to mark the memory as addressable just before the zeroing
6463
   occurs, otherwise you'll get a lot of invalid write errors.  For example,
6464
   you'll need to do this if your allocator recycles freed blocks, but it
6465
   zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
6466
   Alternatively, if your allocator reuses freed blocks for allocator-internal
6467
   data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
6468
6469
   Really, what's happening is a blurring of the lines between the client
6470
   program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
6471
   memory should be considered unaddressable to the client program, but the
6472
   allocator knows more than the rest of the client program and so may be able
6473
   to safely access it.  Extra client requests are necessary for Valgrind to
6474
   understand the distinction between the allocator and the rest of the
6475
   program.
6476
6477
   Ignored if addr == 0.
6478
*/
6479
#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed)          \
6480
252
    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MALLOCLIKE_BLOCK,       \
6481
252
                                    addr, sizeB, rzB, is_zeroed, 0)
6482
6483
/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
6484
   Ignored if addr == 0.
6485
*/
6486
#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB)     \
6487
    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RESIZEINPLACE_BLOCK,    \
6488
                                    addr, oldSizeB, newSizeB, rzB, 0)
6489
6490
/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
6491
   Ignored if addr == 0.
6492
*/
6493
#define VALGRIND_FREELIKE_BLOCK(addr, rzB)                              \
6494
0
    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREELIKE_BLOCK,         \
6495
0
                                    addr, rzB, 0, 0, 0)
6496
6497
/* Create a memory pool. */
6498
#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed)             \
6499
    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL,   \
6500
                                    pool, rzB, is_zeroed, 0, 0)
6501
6502
/* Create a memory pool with some flags specifying extended behaviour.
6503
   When flags is zero, the behaviour is identical to VALGRIND_CREATE_MEMPOOL.
6504
   
6505
   The flag VALGRIND_MEMPOOL_METAPOOL specifies that the pieces of memory 
6506
   associated with the pool using VALGRIND_MEMPOOL_ALLOC  will be used
6507
   by the application as superblocks to dole out MALLOC_LIKE blocks using
6508
   VALGRIND_MALLOCLIKE_BLOCK. In other words, a meta pool is a "2 levels"
6509
   pool : first level is the blocks described by VALGRIND_MEMPOOL_ALLOC.
6510
   The second level blocks are described using VALGRIND_MALLOCLIKE_BLOCK.
6511
   Note that the association between the pool and the second level blocks
6512
   is implicit : second level blocks will be located inside first level
6513
   blocks. It is necessary to use the VALGRIND_MEMPOOL_METAPOOL flag
6514
   for such 2 levels pools, as otherwise valgrind will detect overlapping
6515
   memory blocks, and will abort execution (e.g. during leak search).
6516
6517
   Such a meta pool can also be marked as an 'auto free' pool using the flag
6518
   VALGRIND_MEMPOOL_AUTO_FREE, which must be OR-ed together with the
6519
   VALGRIND_MEMPOOL_METAPOOL. For an 'auto free' pool, VALGRIND_MEMPOOL_FREE
6520
   will automatically free the second level blocks that are contained
6521
   inside the first level block freed with VALGRIND_MEMPOOL_FREE.
6522
   In other words, calling VALGRIND_MEMPOOL_FREE will cause implicit calls
6523
   to VALGRIND_FREELIKE_BLOCK for all the second level blocks included
6524
   in the first level block.
6525
   Note: it is an error to use the VALGRIND_MEMPOOL_AUTO_FREE flag
6526
   without the VALGRIND_MEMPOOL_METAPOOL flag.
6527
*/
6528
#define VALGRIND_MEMPOOL_AUTO_FREE  1
6529
#define VALGRIND_MEMPOOL_METAPOOL   2
6530
#define VALGRIND_CREATE_MEMPOOL_EXT(pool, rzB, is_zeroed, flags)        \
6531
   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL,          \
6532
                                   pool, rzB, is_zeroed, flags, 0)
6533
6534
/* Destroy a memory pool. */
6535
#define VALGRIND_DESTROY_MEMPOOL(pool)                            \
6536
    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DESTROY_MEMPOOL,  \
6537
                                    pool, 0, 0, 0, 0)
6538
6539
/* Associate a piece of memory with a memory pool. */
6540
#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size)                  \
6541
    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_ALLOC,    \
6542
                                    pool, addr, size, 0, 0)
6543
6544
/* Disassociate a piece of memory from a memory pool. */
6545
#define VALGRIND_MEMPOOL_FREE(pool, addr)                         \
6546
    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_FREE,     \
6547
                                    pool, addr, 0, 0, 0)
6548
6549
/* Disassociate any pieces outside a particular range. */
6550
#define VALGRIND_MEMPOOL_TRIM(pool, addr, size)                   \
6551
    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_TRIM,     \
6552
                                    pool, addr, size, 0, 0)
6553
6554
/* Resize and/or move a piece associated with a memory pool. */
6555
#define VALGRIND_MOVE_MEMPOOL(poolA, poolB)                       \
6556
    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MOVE_MEMPOOL,     \
6557
                                    poolA, poolB, 0, 0, 0)
6558
6559
/* Resize and/or move a piece associated with a memory pool. */
6560
#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size)         \
6561
    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_CHANGE,   \
6562
                                    pool, addrA, addrB, size, 0)
6563
6564
/* Return 1 if a mempool exists, else 0. */
6565
#define VALGRIND_MEMPOOL_EXISTS(pool)                             \
6566
    (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                  \
6567
                               VG_USERREQ__MEMPOOL_EXISTS,        \
6568
                               pool, 0, 0, 0, 0)
6569
6570
/* Mark a piece of memory as being a stack. Returns a stack id.
6571
   start is the lowest addressable stack byte, end is the highest
6572
   addressable stack byte. */
6573
#define VALGRIND_STACK_REGISTER(start, end)                       \
6574
    (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                  \
6575
                               VG_USERREQ__STACK_REGISTER,        \
6576
                               start, end, 0, 0, 0)
6577
6578
/* Unmark the piece of memory associated with a stack id as being a
6579
   stack. */
6580
#define VALGRIND_STACK_DEREGISTER(id)                             \
6581
    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_DEREGISTER, \
6582
                                    id, 0, 0, 0, 0)
6583
6584
/* Change the start and end address of the stack id.
6585
   start is the new lowest addressable stack byte, end is the new highest
6586
   addressable stack byte. */
6587
#define VALGRIND_STACK_CHANGE(id, start, end)                     \
6588
    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_CHANGE,     \
6589
                                    id, start, end, 0, 0)
6590
6591
/* Load PDB debug info for Wine PE image_map. */
6592
#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta)     \
6593
    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LOAD_PDB_DEBUGINFO, \
6594
                                    fd, ptr, total_size, delta, 0)
6595
6596
/* Map a code address to a source file name and line number.  buf64
6597
   must point to a 64-byte buffer in the caller's address space.  The
6598
   result will be dumped in there and is guaranteed to be zero
6599
   terminated.  If no info is found, the first byte is set to zero. */
6600
#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64)                    \
6601
    (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0,                  \
6602
                               VG_USERREQ__MAP_IP_TO_SRCLOC,      \
6603
                               addr, buf64, 0, 0, 0)
6604
6605
/* Disable error reporting for this thread.  Behaves in a stack like
6606
   way, so you can safely call this multiple times provided that
6607
   VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times
6608
   to re-enable reporting.  The first call of this macro disables
6609
   reporting.  Subsequent calls have no effect except to increase the
6610
   number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable
6611
   reporting.  Child threads do not inherit this setting from their
6612
   parents -- they are always created with reporting enabled. */
6613
#define VALGRIND_DISABLE_ERROR_REPORTING                                \
6614
    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
6615
                                    1, 0, 0, 0, 0)
6616
6617
/* Re-enable error reporting, as per comments on
6618
   VALGRIND_DISABLE_ERROR_REPORTING. */
6619
#define VALGRIND_ENABLE_ERROR_REPORTING                                 \
6620
    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
6621
                                    -1, 0, 0, 0, 0)
6622
6623
/* Execute a monitor command from the client program.
6624
   If a connection is opened with GDB, the output will be sent
6625
   according to the output mode set for vgdb.
6626
   If no connection is opened, output will go to the log output.
6627
   Returns 1 if command not recognised, 0 otherwise. */
6628
#define VALGRIND_MONITOR_COMMAND(command)                               \
6629
   VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__GDB_MONITOR_COMMAND, \
6630
                                   command, 0, 0, 0, 0)
6631
6632
6633
#undef PLAT_x86_darwin
6634
#undef PLAT_amd64_darwin
6635
#undef PLAT_x86_win32
6636
#undef PLAT_amd64_win64
6637
#undef PLAT_x86_linux
6638
#undef PLAT_amd64_linux
6639
#undef PLAT_ppc32_linux
6640
#undef PLAT_ppc64be_linux
6641
#undef PLAT_ppc64le_linux
6642
#undef PLAT_arm_linux
6643
#undef PLAT_s390x_linux
6644
#undef PLAT_mips32_linux
6645
#undef PLAT_mips64_linux
6646
#undef PLAT_x86_solaris
6647
#undef PLAT_amd64_solaris
6648
6649
#endif   /* __VALGRIND_H */