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