Coverage Report

Created: 2025-12-31 07:23

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