Home | History | Annotate | Download | only in coregrind
      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-2015 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 (at) 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}.  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} ------------ */
    381 
    382 #if defined(VGP_amd64_linux) || defined(VGP_amd64_darwin)
    383 
    384 __asm__(
    385 ".text"  "\n"
    386 ""       "\n"
    387 
    388 #if defined(VGP_amd64_linux)
    389 ".global VG_MINIMAL_SETJMP"  "\n"  // rdi = jmp_buf
    390 "VG_MINIMAL_SETJMP:"  "\n"
    391 
    392 #elif defined(VGP_amd64_darwin)
    393 ".globl _VG_MINIMAL_SETJMP"  "\n"  // rdi = jmp_buf
    394 "_VG_MINIMAL_SETJMP:"  "\n"
    395 
    396 #else
    397 #   error "Huh?"
    398 #endif
    399 
    400 "        movq   %rax,   0(%rdi)"   "\n"
    401 "        movq   %rbx,   8(%rdi)"   "\n"
    402 "        movq   %rcx,  16(%rdi)"   "\n"
    403 "        movq   %rdx,  24(%rdi)"   "\n"
    404 "        movq   %rdi,  32(%rdi)"   "\n"
    405 "        movq   %rsi,  40(%rdi)"   "\n"
    406 "        movq   %rbp,  48(%rdi)"   "\n"
    407 "        movq   %rsp,  56(%rdi)"   "\n"
    408 "        movq   %r8,   64(%rdi)"   "\n"
    409 "        movq   %r9,   72(%rdi)"   "\n"
    410 "        movq   %r10,  80(%rdi)"   "\n"
    411 "        movq   %r11,  88(%rdi)"   "\n"
    412 "        movq   %r12,  96(%rdi)"   "\n"
    413 "        movq   %r13, 104(%rdi)"   "\n"
    414 "        movq   %r14, 112(%rdi)"   "\n"
    415 "        movq   %r15, 120(%rdi)"   "\n"
    416          // store the return address
    417 "        movq   0(%rsp), %rax"     "\n"
    418 "        movq   %rax, 128(%rdi)"   "\n"
    419          // and return zero
    420 "        movq   $0, %rax"          "\n"
    421 "        ret"                      "\n"
    422 ""       "\n"
    423 
    424 
    425 #if defined(VGP_amd64_linux)
    426 ".global VG_MINIMAL_LONGJMP"  "\n"
    427 "VG_MINIMAL_LONGJMP:"  "\n"    // rdi = jmp_buf
    428 
    429 #elif defined(VGP_amd64_darwin)
    430 ".globl _VG_MINIMAL_LONGJMP"  "\n"
    431 "_VG_MINIMAL_LONGJMP:"  "\n"    // rdi = jmp_buf
    432 
    433 #else
    434 #   error "Huh?"
    435 #endif
    436          // skip restoring rax; it's pointless
    437 "        movq     8(%rdi),  %rbx"    "\n"
    438 "        movq    16(%rdi),  %rcx"    "\n"
    439 "        movq    24(%rdi),  %rdx"    "\n"
    440          // defer restoring rdi; we still need it
    441 "        movq    40(%rdi),  %rsi"    "\n"
    442 "        movq    48(%rdi),  %rbp"    "\n"
    443 "        movq    56(%rdi),  %rsp"    "\n"
    444 "        movq    64(%rdi),  %r8"     "\n"
    445 "        movq    72(%rdi),  %r9"     "\n"
    446 "        movq    80(%rdi),  %r10"    "\n"
    447 "        movq    88(%rdi),  %r11"    "\n"
    448 "        movq    96(%rdi),  %r12"    "\n"
    449 "        movq   104(%rdi),  %r13"    "\n"
    450 "        movq   112(%rdi),  %r14"    "\n"
    451 "        movq   120(%rdi),  %r15"    "\n"
    452          // restore the return address
    453 "        movq   128(%rdi), %rax"     "\n"
    454          // restore rdi; this is the last use
    455 "        movq   32(%rdi), %rdi"      "\n"
    456          // make %rsp look like we really did a return
    457 "        addq   $8, %rsp"            "\n"
    458          // continue at RA of original call.  Note: this is a
    459          // nasty trick.  We assume that %rax is nonzero, and so the
    460          // caller can differentiate this case from the normal _SETJMP
    461          // return case.  If the return address ever is zero, then
    462          // we're hosed; but that seems pretty unlikely given that it
    463          // would mean we'd be executing at the wraparound point of the
    464          // address space.
    465 "        jmp *%rax"                  "\n"
    466 ""       "\n"
    467 
    468 #if !defined(VGP_amd64_darwin)
    469 ".previous"       "\n"
    470 #endif
    471 );
    472 
    473 #endif /* VGP_amd64_linux || VGP_amd64_darwin */
    474 
    475 
    476 /* ------------ x86-{linux,darwin} ------------ */
    477 
    478 #if defined(VGP_x86_linux) || defined(VGP_x86_darwin)
    479 
    480 __asm__(
    481 ".text"  "\n"
    482 ""       "\n"
    483 
    484 #if defined(VGP_x86_linux)
    485 ".global VG_MINIMAL_SETJMP"  "\n"  // eax = jmp_buf
    486 "VG_MINIMAL_SETJMP:"  "\n"
    487 
    488 #elif defined(VGP_x86_darwin)
    489 ".globl _VG_MINIMAL_SETJMP"  "\n"  // eax = jmp_buf
    490 "_VG_MINIMAL_SETJMP:"  "\n"
    491 
    492 #else
    493 #   error "Huh?"
    494 #endif
    495 
    496 "        movl   %eax,   0(%eax)"   "\n"
    497 "        movl   %ebx,   4(%eax)"   "\n"
    498 "        movl   %ecx,   8(%eax)"   "\n"
    499 "        movl   %edx,  12(%eax)"   "\n"
    500 "        movl   %edi,  16(%eax)"   "\n"
    501 "        movl   %esi,  20(%eax)"   "\n"
    502 "        movl   %ebp,  24(%eax)"   "\n"
    503 "        movl   %esp,  28(%eax)"   "\n"
    504          // store the return address
    505 "        movl   0(%esp), %ebx"     "\n"
    506 "        movl   %ebx, 32(%eax)"    "\n"
    507          // un-trash ebx (necessary?  i don't know)
    508 "        movl   4(%eax), %ebx"     "\n"
    509          // and return zero
    510 "        movl   $0, %eax"          "\n"
    511 "        ret"                      "\n"
    512 ""       "\n"
    513 
    514 
    515 #if defined(VGP_x86_linux)
    516 ".global VG_MINIMAL_LONGJMP"  "\n"
    517 "VG_MINIMAL_LONGJMP:"  "\n"    // eax = jmp_buf
    518 
    519 #elif defined(VGP_x86_darwin)
    520 ".globl _VG_MINIMAL_LONGJMP"  "\n"
    521 "_VG_MINIMAL_LONGJMP:"  "\n"    // eax = jmp_buf
    522 
    523 #else
    524 #   error "Huh?"
    525 #endif
    526 
    527          // skip restoring eax; it's pointless
    528 "        movl     4(%eax),  %ebx"    "\n"
    529 "        movl     8(%eax),  %ecx"    "\n"
    530 "        movl    12(%eax),  %edx"    "\n"
    531 "        movl    16(%eax),  %edi"    "\n"
    532 "        movl    20(%eax),  %esi"    "\n"
    533 "        movl    24(%eax),  %ebp"    "\n"
    534 "        movl    28(%eax),  %esp"    "\n"
    535          // restore the return address
    536 "        movl    32(%eax), %eax"     "\n"
    537          // make %esp look like we really did a return
    538 "        addl    $4, %esp"           "\n"
    539          // continue at RA of original call.  Same zero-vs-nonzero
    540          // trick/assumption as documented for the amd64-linux case.
    541 "        jmp *%eax"                  "\n"
    542 ""       "\n"
    543 
    544 #if !defined(VGP_x86_darwin)
    545 ".previous"       "\n"
    546 #endif
    547 );
    548 
    549 #endif /* VGP_x86_linux || VGP_x86_darwin */
    550 
    551 #if defined(VGP_mips32_linux)
    552 
    553 __asm__(
    554 ".text                          \n\t"
    555 ".globl VG_MINIMAL_SETJMP;      \n\t"
    556 ".align 2;                      \n\t"
    557 "VG_MINIMAL_SETJMP:             \n\t"  /* a0 = jmp_buf */
    558 "   sw   $s0,  0($a0)           \n\t"  /* Save registers s0-s7. */
    559 "   sw   $s1,  4($a0)           \n\t"
    560 "   sw   $s2,  8($a0)           \n\t"
    561 "   sw   $s3, 12($a0)           \n\t"
    562 "   sw   $s4, 16($a0)           \n\t"
    563 "   sw   $s5, 20($a0)           \n\t"
    564 "   sw   $s6, 24($a0)           \n\t"
    565 "   sw   $s7, 28($a0)           \n\t"
    566 "   sw   $s8, 32($a0)           \n\t"  /* Frame pointer. */
    567 "   sw   $ra, 36($a0)           \n\t"  /* Return address. */
    568 "   sw   $gp, 40($a0)           \n\t"  /* Global data pointer. */
    569 "   sw   $sp, 44($a0)           \n\t"  /* Stack pointer. */
    570 
    571 "   move $v0, $zero             \n\t"  /* Return zero. */
    572 "   j    $ra                    \n\t"
    573 "   nop                         \n\t"
    574 ".previous                      \n\t"
    575 "                               \n\t"
    576 ".globl VG_MINIMAL_LONGJMP;     \n\t"
    577 ".align 2;                      \n\t"
    578 "VG_MINIMAL_LONGJMP:            \n\t"  /* a0 = jmp_buf */
    579 "   lw   $s0,  0($a0)           \n\t"  /* Restore registers s0-s7. */
    580 "   lw   $s1,  4($a0)           \n\t"
    581 "   lw   $s2,  8($a0)           \n\t"
    582 "   lw   $s3, 12($a0)           \n\t"
    583 "   lw   $s4, 16($a0)           \n\t"
    584 "   lw   $s5, 20($a0)           \n\t"
    585 "   lw   $s6, 24($a0)           \n\t"
    586 "   lw   $s7, 28($a0)           \n\t"
    587 "   lw   $s8, 32($a0)           \n\t"  /* Frame pointer. */
    588 "   lw   $ra, 36($a0)           \n\t"  /* Return address. */
    589 "   lw   $gp, 40($a0)           \n\t"  /* Global data pointer. */
    590 "   lw   $sp, 44($a0)           \n\t"  /* Stack pointer. */
    591 
    592 /* Checking whether second argument is zero. */
    593 "   bnez $a1, 1f                \n\t"
    594 "   nop                         \n\t"
    595 "   addi $a1, $a1, 1            \n\t"  /* We must return 1 if val=0. */
    596 "1:                             \n\t"
    597 "   move $v0, $a1               \n\t"  /* Return value of second argument. */
    598 "   j    $ra                    \n\t"
    599 "   nop                         \n\t"
    600 ".previous                      \n\t"
    601 );
    602 #endif  /* VGP_mips32_linux */
    603 
    604 /*--------------------------------------------------------------------*/
    605 /*--- end                                                          ---*/
    606 /*--------------------------------------------------------------------*/
    607