• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*--------------------------------------------------------------------*/
3 /*--- A minimal setjmp/longjmp implementation.      m_libcsetjmp.c ---*/
4 /*--------------------------------------------------------------------*/
5 
6 /*
7    This file is part of Valgrind, a dynamic binary instrumentation
8    framework.
9 
10    Copyright (C) 2010-2017 Mozilla Inc
11 
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.
16 
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.
21 
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25    02111-1307, USA.
26 
27    The GNU General Public License is contained in the file COPYING.
28 */
29 
30 /* Contributed by Julian Seward <jseward@acm.org> */
31 
32 
33 #include "pub_core_basics.h"
34 #include "pub_core_libcsetjmp.h"    /* self */
35 
36 
37 /* See include/pub_tool_libcsetjmp.h for background and rationale. */
38 
39 /* The alternative implementations are for ppc{32,64}-linux and
40    {amd64,x86}-{linux,darwin,solaris}.  See #259977.  That leaves only
41    {arm,s390x}-linux using the gcc builtins now.
42 */
43 
44 /* ------------ ppc32-linux ------------ */
45 
46 #if defined(VGP_ppc32_linux)
47 
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"
93 
94 
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"
143 
144 ".previous"  "\n"
145 );
146 
147 #endif /* VGP_ppc32_linux */
148 
149 
150 /* ------------ ppc64-linux ------------ */
151 
152 #if defined(VGP_ppc64be_linux)
153 
154 __asm__(
155 ".section \".toc\",\"aw\""          "\n"
156 
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"
166 
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"
209 
210 
211 ".globl VG_MINIMAL_LONGJMP"         "\n"
212 
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"
218 
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"
267 
268 ".previous"  "\n"
269 );
270 
271 #elif defined(VGP_ppc64le_linux)
272 __asm__(
273 ".section \".toc\",\"aw\""          "\n"
274 
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"
322 
323 
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"
374 
375 ".previous"  "\n"
376 );
377 #endif /* VGP_ppc64be_linux */
378 
379 
380 /* -------- amd64-{linux,darwin,solaris} -------- */
381 
382 #if defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) || \
383     defined(VGP_amd64_solaris)
384 
385 __asm__(
386 ".text"  "\n"
387 ""       "\n"
388 
389 #if defined(VGP_amd64_linux) || defined(VGP_amd64_solaris)
390 ".global VG_MINIMAL_SETJMP"  "\n"  // rdi = jmp_buf
391 "VG_MINIMAL_SETJMP:"  "\n"
392 
393 #elif defined(VGP_amd64_darwin)
394 ".globl _VG_MINIMAL_SETJMP"  "\n"  // rdi = jmp_buf
395 "_VG_MINIMAL_SETJMP:"  "\n"
396 
397 #else
398 #   error "Huh?"
399 #endif
400 
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"
424 
425 
426 #if defined(VGP_amd64_linux) || defined(VGP_amd64_solaris)
427 ".global VG_MINIMAL_LONGJMP"  "\n"
428 "VG_MINIMAL_LONGJMP:"  "\n"    // rdi = jmp_buf
429 
430 #elif defined(VGP_amd64_darwin)
431 ".globl _VG_MINIMAL_LONGJMP"  "\n"
432 "_VG_MINIMAL_LONGJMP:"  "\n"    // rdi = jmp_buf
433 
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"
468 
469 #if !defined(VGP_amd64_darwin)
470 ".previous"       "\n"
471 #endif
472 );
473 
474 #endif /* VGP_amd64_linux || VGP_amd64_darwin || VGP_amd64_solaris */
475 
476 
477 /* -------- x86-{linux,darwin,solaris} -------- */
478 
479 #if defined(VGP_x86_linux) || defined(VGP_x86_darwin) || \
480     defined(VGP_x86_solaris)
481 
482 __asm__(
483 ".text"  "\n"
484 ""       "\n"
485 
486 #if defined(VGP_x86_linux) || defined(VGP_x86_solaris)
487 ".global VG_MINIMAL_SETJMP"  "\n"  // eax = jmp_buf
488 "VG_MINIMAL_SETJMP:"  "\n"
489 
490 #elif defined(VGP_x86_darwin)
491 ".globl _VG_MINIMAL_SETJMP"  "\n"  // eax = jmp_buf
492 "_VG_MINIMAL_SETJMP:"  "\n"
493 
494 #else
495 #   error "Huh?"
496 #endif
497 
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"
515 
516 
517 #if defined(VGP_x86_linux) || defined(VGP_x86_solaris)
518 ".global VG_MINIMAL_LONGJMP"  "\n"
519 "VG_MINIMAL_LONGJMP:"  "\n"    // eax = jmp_buf
520 
521 #elif defined(VGP_x86_darwin)
522 ".globl _VG_MINIMAL_LONGJMP"  "\n"
523 "_VG_MINIMAL_LONGJMP:"  "\n"    // eax = jmp_buf
524 
525 #else
526 #   error "Huh?"
527 #endif
528 
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"
545 
546 #if !defined(VGP_x86_darwin)
547 ".previous"       "\n"
548 #endif
549 );
550 
551 #endif /* VGP_x86_linux || VGP_x86_darwin || VGP_x86_solaris */
552 
553 #if defined(VGP_mips32_linux)
554 
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"
618 );
619 #endif  /* VGP_mips32_linux */
620 
621 #if defined(VGP_mips64_linux)
622 
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"
690 );
691 #endif  /* VGP_mips64_linux */
692 
693 /*--------------------------------------------------------------------*/
694 /*--- end                                                          ---*/
695 /*--------------------------------------------------------------------*/
696