FreeBSD: add file descriptor tracking for _umtx_op
[valgrind.git] / coregrind / m_libcsetjmp.c
blob02324daab7570e7e777f9b20895b1af212b78614
2 /*--------------------------------------------------------------------*/
3 /*--- A minimal setjmp/longjmp implementation. m_libcsetjmp.c ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2010-2017 Mozilla Foundation
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation; either version 2 of the
15 License, or (at your option) any later version.
17 This program is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, see <http://www.gnu.org/licenses/>.
25 The GNU General Public License is contained in the file COPYING.
28 /* Contributed by Julian Seward <jseward@acm.org> */
30 /* This file must be compiled without link time optimisation, as otherwise
31 the asm functions below become undefined references at link time for
32 unclear reasons. */
34 #include "pub_core_basics.h"
35 #include "pub_core_libcsetjmp.h" /* self */
37 /* See include/pub_tool_libcsetjmp.h for background and rationale. */
39 /* The alternative implementations are for s390x-linux, ppc{32,64}-linux, and
40 {amd64,x86}-{linux,darwin,solaris,freebsd}. See #259977. That leaves only
41 arm-linux using the gcc builtins now.
44 /* ------------ ppc32-linux ------------ */
46 #if defined(VGP_ppc32_linux)
48 __asm__(
49 ".text" "\n"
50 "" "\n"
51 ".global VG_MINIMAL_SETJMP" "\n" // r3 = jmp_buf
52 "VG_MINIMAL_SETJMP:" "\n"
53 " stw 0, 0(3)" "\n"
54 " stw 1, 4(3)" "\n"
55 " stw 2, 8(3)" "\n"
56 " stw 3, 12(3)" "\n"
57 " stw 4, 16(3)" "\n"
58 " stw 5, 20(3)" "\n"
59 " stw 6, 24(3)" "\n"
60 " stw 7, 28(3)" "\n"
61 " stw 8, 32(3)" "\n"
62 " stw 9, 36(3)" "\n"
63 " stw 10, 40(3)" "\n"
64 " stw 11, 44(3)" "\n"
65 " stw 12, 48(3)" "\n"
66 " stw 13, 52(3)" "\n"
67 " stw 14, 56(3)" "\n"
68 " stw 15, 60(3)" "\n"
69 " stw 16, 64(3)" "\n"
70 " stw 17, 68(3)" "\n"
71 " stw 18, 72(3)" "\n"
72 " stw 19, 76(3)" "\n"
73 " stw 20, 80(3)" "\n"
74 " stw 21, 84(3)" "\n"
75 " stw 22, 88(3)" "\n"
76 " stw 23, 92(3)" "\n"
77 " stw 24, 96(3)" "\n"
78 " stw 25, 100(3)" "\n"
79 " stw 26, 104(3)" "\n"
80 " stw 27, 108(3)" "\n"
81 " stw 28, 112(3)" "\n"
82 " stw 29, 116(3)" "\n"
83 " stw 30, 120(3)" "\n"
84 " stw 31, 124(3)" "\n"
85 // must use a caller-save register here as scratch, hence r4
86 " mflr 4" "\n"
87 " stw 4, 128(3)" "\n"
88 " mfcr 4" "\n"
89 " stw 4, 132(3)" "\n"
90 " li 3, 0" "\n"
91 " blr" "\n"
92 "" "\n"
95 ".global VG_MINIMAL_LONGJMP" "\n"
96 "VG_MINIMAL_LONGJMP:" "\n" // r3 = jmp_buf
97 // do r4 = 1
98 // and park it in the restore slot for r3 (the ret reg)
99 " li 4, 1" "\n"
100 " stw 4, 12(3)" "\n"
101 // restore everything except r3
102 // then r3 last of all
103 // then blr
104 " lwz 0, 128(3)" "\n"
105 " mtlr 0" "\n"
106 " lwz 0, 132(3)" "\n"
107 " mtcr 0" "\n"
108 " lwz 0, 0(3)" "\n"
109 " lwz 1, 4(3)" "\n"
110 " lwz 2, 8(3)" "\n"
111 // r3 is done at the end
112 " lwz 4, 16(3)" "\n"
113 " lwz 5, 20(3)" "\n"
114 " lwz 6, 24(3)" "\n"
115 " lwz 7, 28(3)" "\n"
116 " lwz 8, 32(3)" "\n"
117 " lwz 9, 36(3)" "\n"
118 " lwz 10, 40(3)" "\n"
119 " lwz 11, 44(3)" "\n"
120 " lwz 12, 48(3)" "\n"
121 " lwz 13, 52(3)" "\n"
122 " lwz 14, 56(3)" "\n"
123 " lwz 15, 60(3)" "\n"
124 " lwz 16, 64(3)" "\n"
125 " lwz 17, 68(3)" "\n"
126 " lwz 18, 72(3)" "\n"
127 " lwz 19, 76(3)" "\n"
128 " lwz 20, 80(3)" "\n"
129 " lwz 21, 84(3)" "\n"
130 " lwz 22, 88(3)" "\n"
131 " lwz 23, 92(3)" "\n"
132 " lwz 24, 96(3)" "\n"
133 " lwz 25, 100(3)" "\n"
134 " lwz 26, 104(3)" "\n"
135 " lwz 27, 108(3)" "\n"
136 " lwz 28, 112(3)" "\n"
137 " lwz 29, 116(3)" "\n"
138 " lwz 30, 120(3)" "\n"
139 " lwz 31, 124(3)" "\n"
140 " lwz 3, 12(3)" "\n"
141 " blr" "\n"
142 "" "\n"
144 ".previous" "\n"
147 #endif /* VGP_ppc32_linux */
150 /* ------------ ppc64-linux ------------ */
152 #if defined(VGP_ppc64be_linux)
154 __asm__(
155 ".section \".toc\",\"aw\"" "\n"
157 ".section \".text\"" "\n"
158 ".align 2" "\n"
159 ".p2align 4,,15" "\n"
160 ".globl VG_MINIMAL_SETJMP" "\n"
161 ".section \".opd\",\"aw\"" "\n"
162 ".align 3" "\n"
163 "VG_MINIMAL_SETJMP:" "\n"
164 ".quad .L.VG_MINIMAL_SETJMP,.TOC.@tocbase,0" "\n"
165 ".previous" "\n"
167 ".type VG_MINIMAL_SETJMP, @function" "\n"
168 ".L.VG_MINIMAL_SETJMP:" "\n"
169 " std 0, 0(3)" "\n"
170 " std 1, 8(3)" "\n"
171 " std 2, 16(3)" "\n"
172 " std 3, 24(3)" "\n"
173 " std 4, 32(3)" "\n"
174 " std 5, 40(3)" "\n"
175 " std 6, 48(3)" "\n"
176 " std 7, 56(3)" "\n"
177 " std 8, 64(3)" "\n"
178 " std 9, 72(3)" "\n"
179 " std 10, 80(3)" "\n"
180 " std 11, 88(3)" "\n"
181 " std 12, 96(3)" "\n"
182 " std 13, 104(3)" "\n"
183 " std 14, 112(3)" "\n"
184 " std 15, 120(3)" "\n"
185 " std 16, 128(3)" "\n"
186 " std 17, 136(3)" "\n"
187 " std 18, 144(3)" "\n"
188 " std 19, 152(3)" "\n"
189 " std 20, 160(3)" "\n"
190 " std 21, 168(3)" "\n"
191 " std 22, 176(3)" "\n"
192 " std 23, 184(3)" "\n"
193 " std 24, 192(3)" "\n"
194 " std 25, 200(3)" "\n"
195 " std 26, 208(3)" "\n"
196 " std 27, 216(3)" "\n"
197 " std 28, 224(3)" "\n"
198 " std 29, 232(3)" "\n"
199 " std 30, 240(3)" "\n"
200 " std 31, 248(3)" "\n"
201 // must use a caller-save register here as scratch, hence r4
202 " mflr 4" "\n"
203 " std 4, 256(3)" "\n"
204 " mfcr 4" "\n"
205 " std 4, 264(3)" "\n"
206 " li 3, 0" "\n"
207 " blr" "\n"
208 "" "\n"
211 ".globl VG_MINIMAL_LONGJMP" "\n"
213 ".section \".opd\",\"aw\"" "\n"
214 ".align 3" "\n"
215 "VG_MINIMAL_LONGJMP:" "\n"
216 ".quad .L.VG_MINIMAL_LONGJMP,.TOC.@tocbase,0" "\n"
217 ".previous" "\n"
219 ".type VG_MINIMAL_LONGJMP, @function" "\n"
220 ".L.VG_MINIMAL_LONGJMP:" "\n"
221 // do r4 = 1
222 // and park it in the restore slot for r3 (the ret reg)
223 " li 4, 1" "\n"
224 " std 4, 24(3)" "\n"
225 // restore everything except r3
226 // then r3 last of all
227 // then blr
228 " ld 0, 256(3)" "\n"
229 " mtlr 0" "\n"
230 " ld 0, 264(3)" "\n"
231 " mtcr 0" "\n"
232 " ld 0, 0(3)" "\n"
233 " ld 1, 8(3)" "\n"
234 " ld 2, 16(3)" "\n"
235 // r3 is done at the end
236 " ld 4, 32(3)" "\n"
237 " ld 5, 40(3)" "\n"
238 " ld 6, 48(3)" "\n"
239 " ld 7, 56(3)" "\n"
240 " ld 8, 64(3)" "\n"
241 " ld 9, 72(3)" "\n"
242 " ld 10, 80(3)" "\n"
243 " ld 11, 88(3)" "\n"
244 " ld 12, 96(3)" "\n"
245 " ld 13, 104(3)" "\n"
246 " ld 14, 112(3)" "\n"
247 " ld 15, 120(3)" "\n"
248 " ld 16, 128(3)" "\n"
249 " ld 17, 136(3)" "\n"
250 " ld 18, 144(3)" "\n"
251 " ld 19, 152(3)" "\n"
252 " ld 20, 160(3)" "\n"
253 " ld 21, 168(3)" "\n"
254 " ld 22, 176(3)" "\n"
255 " ld 23, 184(3)" "\n"
256 " ld 24, 192(3)" "\n"
257 " ld 25, 200(3)" "\n"
258 " ld 26, 208(3)" "\n"
259 " ld 27, 216(3)" "\n"
260 " ld 28, 224(3)" "\n"
261 " ld 29, 232(3)" "\n"
262 " ld 30, 240(3)" "\n"
263 " ld 31, 248(3)" "\n"
264 " ld 3, 24(3)" "\n"
265 " blr" "\n"
266 "" "\n"
268 ".previous" "\n"
271 #elif defined(VGP_ppc64le_linux)
272 __asm__(
273 ".section \".toc\",\"aw\"" "\n"
275 ".section \".text\"" "\n"
276 ".align 2" "\n"
277 ".p2align 4,,15" "\n"
278 ".globl VG_MINIMAL_SETJMP" "\n"
279 ".type VG_MINIMAL_SETJMP,@function" "\n"
280 "VG_MINIMAL_SETJMP:" "\n"
281 " .localentry VG_MINIMAL_SETJMP, .-VG_MINIMAL_SETJMP" "\n"
282 " std 0, 0(3)" "\n"
283 " std 1, 8(3)" "\n"
284 " std 2, 16(3)" "\n"
285 " std 3, 24(3)" "\n"
286 " std 4, 32(3)" "\n"
287 " std 5, 40(3)" "\n"
288 " std 6, 48(3)" "\n"
289 " std 7, 56(3)" "\n"
290 " std 8, 64(3)" "\n"
291 " std 9, 72(3)" "\n"
292 " std 10, 80(3)" "\n"
293 " std 11, 88(3)" "\n"
294 " std 12, 96(3)" "\n"
295 " std 13, 104(3)" "\n"
296 " std 14, 112(3)" "\n"
297 " std 15, 120(3)" "\n"
298 " std 16, 128(3)" "\n"
299 " std 17, 136(3)" "\n"
300 " std 18, 144(3)" "\n"
301 " std 19, 152(3)" "\n"
302 " std 20, 160(3)" "\n"
303 " std 21, 168(3)" "\n"
304 " std 22, 176(3)" "\n"
305 " std 23, 184(3)" "\n"
306 " std 24, 192(3)" "\n"
307 " std 25, 200(3)" "\n"
308 " std 26, 208(3)" "\n"
309 " std 27, 216(3)" "\n"
310 " std 28, 224(3)" "\n"
311 " std 29, 232(3)" "\n"
312 " std 30, 240(3)" "\n"
313 " std 31, 248(3)" "\n"
314 // must use a caller-save register here as scratch, hence r4
315 " mflr 4" "\n"
316 " std 4, 256(3)" "\n"
317 " mfcr 4" "\n"
318 " std 4, 264(3)" "\n"
319 " li 3, 0" "\n"
320 " blr" "\n"
321 "" "\n"
324 ".globl VG_MINIMAL_LONGJMP" "\n"
325 ".type VG_MINIMAL_LONGJMP, @function" "\n"
326 "VG_MINIMAL_LONGJMP:" "\n"
327 " .localentry VG_MINIMAL_LONGJMP, .-VG_MINIMAL_LONGJMP" "\n"
328 // do r4 = 1
329 // and park it in the restore slot for r3 (the ret reg)
330 " li 4, 1" "\n"
331 " std 4, 24(3)" "\n"
332 // restore everything except r3
333 // then r3 last of all
334 // then blr
335 " ld 0, 256(3)" "\n"
336 " mtlr 0" "\n"
337 " ld 0, 264(3)" "\n"
338 " mtcr 0" "\n"
339 " ld 0, 0(3)" "\n"
340 " ld 1, 8(3)" "\n"
341 " ld 2, 16(3)" "\n"
342 // r3 is done at the end
343 " ld 4, 32(3)" "\n"
344 " ld 5, 40(3)" "\n"
345 " ld 6, 48(3)" "\n"
346 " ld 7, 56(3)" "\n"
347 " ld 8, 64(3)" "\n"
348 " ld 9, 72(3)" "\n"
349 " ld 10, 80(3)" "\n"
350 " ld 11, 88(3)" "\n"
351 " ld 12, 96(3)" "\n"
352 " ld 13, 104(3)" "\n"
353 " ld 14, 112(3)" "\n"
354 " ld 15, 120(3)" "\n"
355 " ld 16, 128(3)" "\n"
356 " ld 17, 136(3)" "\n"
357 " ld 18, 144(3)" "\n"
358 " ld 19, 152(3)" "\n"
359 " ld 20, 160(3)" "\n"
360 " ld 21, 168(3)" "\n"
361 " ld 22, 176(3)" "\n"
362 " ld 23, 184(3)" "\n"
363 " ld 24, 192(3)" "\n"
364 " ld 25, 200(3)" "\n"
365 " ld 26, 208(3)" "\n"
366 " ld 27, 216(3)" "\n"
367 " ld 28, 224(3)" "\n"
368 " ld 29, 232(3)" "\n"
369 " ld 30, 240(3)" "\n"
370 " ld 31, 248(3)" "\n"
371 " ld 3, 24(3)" "\n"
372 " blr" "\n"
373 "" "\n"
375 ".previous" "\n"
377 #endif /* VGP_ppc64be_linux */
380 /* -------- amd64-{linux,darwin,solaris,freebsd} -------- */
382 #if defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) || \
383 defined(VGP_amd64_solaris) || defined(VGP_amd64_freebsd)
385 __asm__(
386 ".text" "\n"
387 "" "\n"
389 #if defined(VGP_amd64_linux) || defined(VGP_amd64_solaris) || defined(VGP_amd64_freebsd)
390 ".global VG_MINIMAL_SETJMP" "\n" // rdi = jmp_buf
391 "VG_MINIMAL_SETJMP:" "\n"
393 #elif defined(VGP_amd64_darwin)
394 ".globl _VG_MINIMAL_SETJMP" "\n" // rdi = jmp_buf
395 "_VG_MINIMAL_SETJMP:" "\n"
397 #else
398 # error "Huh?"
399 #endif
401 " movq %rax, 0(%rdi)" "\n"
402 " movq %rbx, 8(%rdi)" "\n"
403 " movq %rcx, 16(%rdi)" "\n"
404 " movq %rdx, 24(%rdi)" "\n"
405 " movq %rdi, 32(%rdi)" "\n"
406 " movq %rsi, 40(%rdi)" "\n"
407 " movq %rbp, 48(%rdi)" "\n"
408 " movq %rsp, 56(%rdi)" "\n"
409 " movq %r8, 64(%rdi)" "\n"
410 " movq %r9, 72(%rdi)" "\n"
411 " movq %r10, 80(%rdi)" "\n"
412 " movq %r11, 88(%rdi)" "\n"
413 " movq %r12, 96(%rdi)" "\n"
414 " movq %r13, 104(%rdi)" "\n"
415 " movq %r14, 112(%rdi)" "\n"
416 " movq %r15, 120(%rdi)" "\n"
417 // store the return address
418 " movq 0(%rsp), %rax" "\n"
419 " movq %rax, 128(%rdi)" "\n"
420 // and return zero
421 " movq $0, %rax" "\n"
422 " ret" "\n"
423 "" "\n"
426 #if defined(VGP_amd64_linux) || defined(VGP_amd64_solaris) || defined(VGP_amd64_freebsd)
427 ".global VG_MINIMAL_LONGJMP" "\n"
428 "VG_MINIMAL_LONGJMP:" "\n" // rdi = jmp_buf
430 #elif defined(VGP_amd64_darwin)
431 ".globl _VG_MINIMAL_LONGJMP" "\n"
432 "_VG_MINIMAL_LONGJMP:" "\n" // rdi = jmp_buf
434 #else
435 # error "Huh?"
436 #endif
437 // skip restoring rax; it's pointless
438 " movq 8(%rdi), %rbx" "\n"
439 " movq 16(%rdi), %rcx" "\n"
440 " movq 24(%rdi), %rdx" "\n"
441 // defer restoring rdi; we still need it
442 " movq 40(%rdi), %rsi" "\n"
443 " movq 48(%rdi), %rbp" "\n"
444 " movq 56(%rdi), %rsp" "\n"
445 " movq 64(%rdi), %r8" "\n"
446 " movq 72(%rdi), %r9" "\n"
447 " movq 80(%rdi), %r10" "\n"
448 " movq 88(%rdi), %r11" "\n"
449 " movq 96(%rdi), %r12" "\n"
450 " movq 104(%rdi), %r13" "\n"
451 " movq 112(%rdi), %r14" "\n"
452 " movq 120(%rdi), %r15" "\n"
453 // restore the return address
454 " movq 128(%rdi), %rax" "\n"
455 // restore rdi; this is the last use
456 " movq 32(%rdi), %rdi" "\n"
457 // make %rsp look like we really did a return
458 " addq $8, %rsp" "\n"
459 // continue at RA of original call. Note: this is a
460 // nasty trick. We assume that %rax is nonzero, and so the
461 // caller can differentiate this case from the normal _SETJMP
462 // return case. If the return address ever is zero, then
463 // we're hosed; but that seems pretty unlikely given that it
464 // would mean we'd be executing at the wraparound point of the
465 // address space.
466 " jmp *%rax" "\n"
467 "" "\n"
469 #if !defined(VGP_amd64_darwin)
470 ".previous" "\n"
471 #endif
474 #endif /* VGP_amd64_linux || VGP_amd64_darwin || VGP_amd64_solaris || VGP_amd64_freebsd */
477 /* -------- x86-{linux,darwin,solaris,freebsd} -------- */
479 #if defined(VGP_x86_linux) || defined(VGP_x86_darwin) || \
480 defined(VGP_x86_solaris) || defined(VGP_x86_freebsd)
482 __asm__(
483 ".text" "\n"
484 "" "\n"
486 #if defined(VGP_x86_linux) || defined(VGP_x86_solaris) || defined(VGP_x86_freebsd)
487 ".global VG_MINIMAL_SETJMP" "\n" // eax = jmp_buf
488 "VG_MINIMAL_SETJMP:" "\n"
490 #elif defined(VGP_x86_darwin)
491 ".globl _VG_MINIMAL_SETJMP" "\n" // eax = jmp_buf
492 "_VG_MINIMAL_SETJMP:" "\n"
494 #else
495 # error "Huh?"
496 #endif
498 " movl %eax, 0(%eax)" "\n"
499 " movl %ebx, 4(%eax)" "\n"
500 " movl %ecx, 8(%eax)" "\n"
501 " movl %edx, 12(%eax)" "\n"
502 " movl %edi, 16(%eax)" "\n"
503 " movl %esi, 20(%eax)" "\n"
504 " movl %ebp, 24(%eax)" "\n"
505 " movl %esp, 28(%eax)" "\n"
506 // store the return address
507 " movl 0(%esp), %ebx" "\n"
508 " movl %ebx, 32(%eax)" "\n"
509 // un-trash ebx (necessary? i don't know)
510 " movl 4(%eax), %ebx" "\n"
511 // and return zero
512 " movl $0, %eax" "\n"
513 " ret" "\n"
514 "" "\n"
517 #if defined(VGP_x86_linux) || defined(VGP_x86_solaris) || defined(VGP_x86_freebsd)
518 ".global VG_MINIMAL_LONGJMP" "\n"
519 "VG_MINIMAL_LONGJMP:" "\n" // eax = jmp_buf
521 #elif defined(VGP_x86_darwin)
522 ".globl _VG_MINIMAL_LONGJMP" "\n"
523 "_VG_MINIMAL_LONGJMP:" "\n" // eax = jmp_buf
525 #else
526 # error "Huh?"
527 #endif
529 // skip restoring eax; it's pointless
530 " movl 4(%eax), %ebx" "\n"
531 " movl 8(%eax), %ecx" "\n"
532 " movl 12(%eax), %edx" "\n"
533 " movl 16(%eax), %edi" "\n"
534 " movl 20(%eax), %esi" "\n"
535 " movl 24(%eax), %ebp" "\n"
536 " movl 28(%eax), %esp" "\n"
537 // restore the return address
538 " movl 32(%eax), %eax" "\n"
539 // make %esp look like we really did a return
540 " addl $4, %esp" "\n"
541 // continue at RA of original call. Same zero-vs-nonzero
542 // trick/assumption as documented for the amd64-linux case.
543 " jmp *%eax" "\n"
544 "" "\n"
546 #if !defined(VGP_x86_darwin)
547 ".previous" "\n"
548 #endif
551 #endif /* VGP_x86_linux || VGP_x86_darwin || VGP_x86_solaris || VGP_x86_freebsd */
553 #if defined(VGP_mips32_linux)
555 __asm__(
556 ".text \n\t"
557 ".globl VG_MINIMAL_SETJMP; \n\t"
558 ".set push \n\t"
559 ".set noreorder \n\t"
560 "VG_MINIMAL_SETJMP: \n\t"
561 #if defined(__mips_hard_float)
562 " sdc1 $f20, 56($a0) \n\t"
563 " sdc1 $f22, 64($a0) \n\t"
564 " sdc1 $f24, 72($a0) \n\t"
565 " sdc1 $f26, 80($a0) \n\t"
566 " sdc1 $f28, 88($a0) \n\t"
567 " sdc1 $f30, 96($a0) \n\t"
568 #endif
569 " sw $gp, 44($a0) \n\t"
570 " sw $s0, 8($a0) \n\t"
571 " sw $s1, 12($a0) \n\t"
572 " sw $s2, 16($a0) \n\t"
573 " sw $s3, 20($a0) \n\t"
574 " sw $s4, 24($a0) \n\t"
575 " sw $s5, 28($a0) \n\t"
576 " sw $s6, 32($a0) \n\t"
577 " sw $s7, 36($a0) \n\t"
578 " sw $ra, 0($a0) \n\t"
579 " sw $sp, 4($a0) \n\t"
580 " sw $fp, 40($a0) \n\t"
581 " jr $ra \n\t"
582 " move $v0, $zero \n\t"
583 ".set pop \n\t"
584 ".previous \n\t"
585 " \n\t"
586 ".text \n\t"
587 ".globl VG_MINIMAL_LONGJMP; \n\t"
588 ".set push \n\t"
589 ".set noreorder \n\t"
590 "VG_MINIMAL_LONGJMP: \n\t"
591 #if defined(__mips_hard_float)
592 " ldc1 $f20, 56($a0) \n\t"
593 " ldc1 $f22, 64($a0) \n\t"
594 " ldc1 $f24, 72($a0) \n\t"
595 " ldc1 $f26, 80($a0) \n\t"
596 " ldc1 $f28, 88($a0) \n\t"
597 " ldc1 $f30, 96($a0) \n\t"
598 #endif
599 " lw $gp, 44($a0) \n\t"
600 " lw $s0, 8($a0) \n\t"
601 " lw $s1, 12($a0) \n\t"
602 " lw $s2, 16($a0) \n\t"
603 " lw $s3, 20($a0) \n\t"
604 " lw $s4, 24($a0) \n\t"
605 " lw $s5, 28($a0) \n\t"
606 " lw $s6, 32($a0) \n\t"
607 " lw $s7, 36($a0) \n\t"
608 " lw $ra, 0($a0) \n\t"
609 " lw $sp, 4($a0) \n\t"
610 " bnez $a1, 1f \n\t"
611 " lw $fp, 40($a0) \n\t"
612 " addiu $a1, $a1, 1 \n\t"
613 "1: \n\t"
614 " jr $ra \n\t"
615 " move $v0, $a1 \n\t"
616 ".set pop \n\t"
617 ".previous \n\t"
619 #endif /* VGP_mips32_linux */
621 #if defined(VGP_mips64_linux)
623 __asm__(
624 ".text \n\t"
625 ".globl VG_MINIMAL_SETJMP; \n\t"
626 ".set push \n\t"
627 ".set noreorder \n\t"
628 "VG_MINIMAL_SETJMP: \n\t"
629 #if defined(__mips_hard_float)
630 " sdc1 $f24, 104($a0) \n\t"
631 " sdc1 $f25, 112($a0) \n\t"
632 " sdc1 $f26, 120($a0) \n\t"
633 " sdc1 $f27, 128($a0) \n\t"
634 " sdc1 $f28, 136($a0) \n\t"
635 " sdc1 $f29, 144($a0) \n\t"
636 " sdc1 $f30, 152($a0) \n\t"
637 " sdc1 $f31, 160($a0) \n\t"
638 #endif
639 " sd $gp, 88($a0) \n\t"
640 " sd $s0, 16($a0) \n\t"
641 " sd $s1, 24($a0) \n\t"
642 " sd $s2, 32($a0) \n\t"
643 " sd $s3, 40($a0) \n\t"
644 " sd $s4, 48($a0) \n\t"
645 " sd $s5, 56($a0) \n\t"
646 " sd $s6, 64($a0) \n\t"
647 " sd $s7, 72($a0) \n\t"
648 " sd $ra, 0($a0) \n\t"
649 " sd $sp, 8($a0) \n\t"
650 " sd $fp, 80($a0) \n\t"
651 " jr $ra \n\t"
652 " move $v0, $zero \n\t"
653 ".set pop \n\t"
654 ".previous \n\t"
655 " \n\t"
656 ".text \n\t"
657 ".globl VG_MINIMAL_LONGJMP; \n\t"
658 ".set push \n\t"
659 ".set noreorder \n\t"
660 "VG_MINIMAL_LONGJMP: \n\t"
661 #if defined(__mips_hard_float)
662 " ldc1 $f24, 104($a0) \n\t"
663 " ldc1 $f25, 112($a0) \n\t"
664 " ldc1 $f26, 120($a0) \n\t"
665 " ldc1 $f27, 128($a0) \n\t"
666 " ldc1 $f28, 136($a0) \n\t"
667 " ldc1 $f29, 144($a0) \n\t"
668 " ldc1 $f30, 152($a0) \n\t"
669 " ldc1 $f31, 160($a0) \n\t"
670 #endif
671 " ld $gp, 88($a0) \n\t"
672 " ld $s0, 16($a0) \n\t"
673 " ld $s1, 24($a0) \n\t"
674 " ld $s2, 32($a0) \n\t"
675 " ld $s3, 40($a0) \n\t"
676 " ld $s4, 48($a0) \n\t"
677 " ld $s5, 56($a0) \n\t"
678 " ld $s6, 64($a0) \n\t"
679 " ld $s7, 72($a0) \n\t"
680 " ld $ra, 0($a0) \n\t"
681 " ld $sp, 8($a0) \n\t"
682 " bnez $a1, 1f \n\t"
683 " ld $fp, 80($a0) \n\t"
684 " daddiu $a1, $a1, 1 \n\t"
685 "1: \n\t"
686 " jr $ra \n\t"
687 " move $v0, $a1 \n\t"
688 ".set pop \n\t"
689 ".previous \n\t"
691 #endif /* VGP_mips64_linux */
693 #if defined(VGP_nanomips_linux)
694 __asm__(
695 ".text \n\t"
696 ".globl VG_MINIMAL_SETJMP; \n\t"
697 ".set push \n\t"
698 ".set noreorder \n\t"
699 "VG_MINIMAL_SETJMP: \n\t"
700 " sw $s0, 0($a0) \n\t"
701 " sw $s1, 4($a0) \n\t"
702 " sw $s2, 8($a0) \n\t"
703 " sw $s3, 12($a0) \n\t"
704 " sw $s4, 16($a0) \n\t"
705 " sw $s5, 20($a0) \n\t"
706 " sw $s6, 24($a0) \n\t"
707 " sw $s7, 28($a0) \n\t"
708 " sw $gp, 32($a0) \n\t"
709 " sw $sp, 36($a0) \n\t"
710 " sw $fp, 40($a0) \n\t"
711 " sw $ra, 44($a0) \n\t"
712 " move $a0, $zero \n\t"
713 " jrc $ra \n\t"
714 ".set pop \n\t"
715 ".previous \n\t"
716 " \n\t"
717 ".text \n\t"
718 ".globl VG_MINIMAL_LONGJMP; \n\t"
719 ".set push \n\t"
720 ".set noreorder \n\t"
721 "VG_MINIMAL_LONGJMP: \n\t"
722 " lw $s0, 0($a0) \n\t"
723 " lw $s1, 4($a0) \n\t"
724 " lw $s2, 8($a0) \n\t"
725 " lw $s3, 12($a0) \n\t"
726 " lw $s4, 16($a0) \n\t"
727 " lw $s5, 20($a0) \n\t"
728 " lw $s6, 24($a0) \n\t"
729 " lw $s7, 28($a0) \n\t"
730 " lw $gp, 32($a0) \n\t"
731 " lw $sp, 36($a0) \n\t"
732 " lw $fp, 40($a0) \n\t"
733 " lw $ra, 44($a0) \n\t"
734 " bnezc $a1, 1f \n\t"
735 " addiu $a1, $a1, 1 \n\t"
736 "1: \n\t"
737 " move $a0, $a1 \n\t"
738 " jrc $ra \n\t"
739 ".set pop \n\t"
740 ".previous \n\t"
742 #endif /* VGP_nanomips_linux */
744 /* ------------ s390x-linux ------------ */
746 #if defined(VGP_s390x_linux)
747 __asm__(
748 ".text" "\n"
749 ".align 4" "\n"
750 ".globl VG_MINIMAL_SETJMP" "\n"
751 ".type VG_MINIMAL_SETJMP, @function" "\n"
752 "VG_MINIMAL_SETJMP:" "\n"
753 " stmg 6,15,0(2)" "\n"
754 " std 8,80(2)" "\n"
755 " std 9,88(2)" "\n"
756 " std 10,96(2)" "\n"
757 " std 11,104(2)" "\n"
758 " std 12,112(2)" "\n"
759 " std 13,120(2)" "\n"
760 " std 14,128(2)" "\n"
761 " std 15,136(2)" "\n"
762 // return zero
763 " lghi 2,0" "\n"
764 " br 14" "\n"
766 ".align 4" "\n"
767 ".globl VG_MINIMAL_LONGJMP" "\n"
768 ".type VG_MINIMAL_LONGJMP, @function" "\n"
769 "VG_MINIMAL_LONGJMP:" "\n"
770 " lmg 6,15,0(2)" "\n"
771 " ld 8,80(2)" "\n"
772 " ld 9,88(2)" "\n"
773 " ld 10,96(2)" "\n"
774 " ld 11,104(2)" "\n"
775 " ld 12,112(2)" "\n"
776 " ld 13,120(2)" "\n"
777 " ld 14,128(2)" "\n"
778 " ld 15,136(2)" "\n"
779 // return the argument (nonzero)
780 " br 14" "\n"
782 #endif /* VGP_s390x_linux */
784 #if defined(__clang__) && defined(VGP_arm64_linux)
786 // __builtin_setjmp is not implemented by the standard C library
787 // used on Android in current llvm-based toolchains as of NDK r19.
789 // Here is a custom implementation of Valgrind's "minimal" setjmp
790 // interface. Per the comment at the top of this file, we only need
791 // to save integer registers.
793 // Per the Procedure Call Standard for the ARM 64-bit Architecture
794 // document,
795 // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
796 // Section 5.1.1. General-purpose registers:
797 // >
798 // > A subroutine invocation must preserve the contents of the
799 // > registers r19-r29 and SP."
801 // We also need to save and restore r30, the link register, i.e.
802 // the default destination that a 'ret' instruction branches to.
804 // Note that this document is phrased in terms of 'r' registers
805 // (e.g. "r30") because it aims to be agnostic as to A64 vs A32
806 // instruction sets, but here we are targeting the A64 instruction
807 // set, so we are dealing with 'x' registers.
811 __attribute__((returns_twice))
812 UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env))
814 asm volatile(
815 // x9 is the first of the regular temporary registers
816 // per the above-mentioned Procedule Call Standard document.
817 // Use it as temporary to hold the value of SP, since str does
818 // not accept SP as operand.
819 " mov x9, sp \n"
820 // Store the general-purpose registers that we need to save
821 // per the above discussion.
822 // Note that x30 is the link register.
823 " stp x19, x20, [%[_env], 0] \n"
824 " stp x21, x22, [%[_env], 0x10] \n"
825 " stp x23, x24, [%[_env], 0x20] \n"
826 " stp x25, x26, [%[_env], 0x30] \n"
827 " stp x27, x28, [%[_env], 0x40] \n"
828 " stp x29, x30, [%[_env], 0x50] \n"
829 // Store the value of SP.
830 " str x9, [%[_env], 0x60] \n"
832 // No outputs
834 // Inputs
835 [_env]"r"(_env)
837 // Clobbers.
838 // We have used x9 as a temporary
839 "x9",
840 // We have written to memory locations
841 "memory");
843 // Direct invokation of setjmp always returns 0.
844 // The pseudo returning of the value 1 as a return from longjmp
845 // is implemented in longjmp.
846 return 0;
849 __attribute__((noreturn))
850 void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env))
852 asm volatile(
853 // Loads to match the stores in the above setjmp implementation.
854 " ldp x19, x20, [%[_env], 0] \n"
855 " ldp x21, x22, [%[_env], 0x10] \n"
856 " ldp x23, x24, [%[_env], 0x20] \n"
857 " ldp x25, x26, [%[_env], 0x30] \n"
858 " ldp x27, x28, [%[_env], 0x40] \n"
859 " ldp x29, x30, [%[_env], 0x50] \n"
860 " ldr x9, [%[_env], 0x60] \n"
861 " mov sp, x9 \n"
862 // return as setjmp for the second time, returning 1.
863 // Since we have loaded the link register x30 from the saved buffer
864 // that was set by the above setjmp implementation, the 'ret' instruction
865 // here is going to return to where setjmp was called.
866 // Per the setjmp/longjmp contract, that pseudo second returning
867 // of setjmp should return the value 1.
868 // x0 is holds the integer return value.
869 " mov x0, 1 \n"
870 " ret \n"
872 // No outputs
874 // Inputs
875 [_env]"r"(_env)
877 // Clobbers.
878 // We have used x9 as a temporary
879 "x9");
881 // This statement is unreachable because the above asm statement
882 // unconditionally does a 'ret' instruction. The purpose of this
883 // statement is to silence clang warnings about this function returning
884 // while having the 'noreturn' attribute.
885 __builtin_unreachable();
888 #endif
890 #if defined(VGP_arm64_freebsd)
892 __asm__(
893 ".text\n"
895 ".globl VG_MINIMAL_SETJMP" "\n"
896 "VG_MINIMAL_SETJMP:" "\n" // x0 = jmp_buf
897 " mov x1, sp\n" /* can't STP from sp */
898 " stp x19, x20, [x0, #0x00]\n"
899 " stp x21, x22, [x0, #0x10]\n"
900 " stp x23, x24, [x0, #0x20]\n"
901 " stp x25, x26, [x0, #0x30]\n"
902 " stp x27, x28, [x0, #0x40]\n"
903 " stp x29, x30, [x0, #0x50]\n"
904 " stp x1, xzr, [x0, #0x60]\n"
905 " stp d8, d9, [x0, #0x70]\n"
906 " stp d10, d11, [x0, #0x80]\n"
907 " stp d12, d13, [x0, #0x90]\n"
908 " stp d14, d15, [x0, #0xA0]\n"
909 " mov x0, #0\n" // return 0 on the first return
910 " ret\n"
911 ".previous\n"
913 ".globl VG_MINIMAL_LONGJMP" "\n"
914 " VG_MINIMAL_LONGJMP:" "\n" // x0 = jmp_buf
915 " ldp x19, x20, [x0, #0x00]\n"
916 " ldp x21, x22, [x0, #0x10]\n"
917 " ldp x23, x24, [x0, #0x20]\n"
918 " ldp x25, x26, [x0, #0x30]\n"
919 " ldp x27, x28, [x0, #0x40]\n"
920 " ldp x29, x30, [x0, #0x50]\n"
921 " ldp x1, xzr, [x0, #0x60]\n"
922 " ldp d8, d9, [x0, #0x70]\n"
923 " ldp d10, d11, [x0, #0x80]\n"
924 " ldp d12, d13, [x0, #0x90]\n"
925 " ldp d14, d15, [x0, #0xA0]\n"
926 " mov sp, x1\n"
927 " mov x0, #1\n" // return non-zero on the second return
928 " br lr\n"
929 ".previous\n"
932 #endif
934 /*--------------------------------------------------------------------*/
935 /*--- end ---*/
936 /*--------------------------------------------------------------------*/