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-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 (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,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