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