github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/runtime/sys_openbsd_amd64.s (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 // 5 // System calls and other sys.stuff for AMD64, OpenBSD. 6 // System calls are implemented in libc/libpthread, this file 7 // contains trampolines that convert from Go to C calling convention. 8 // Some direct system call implementations currently remain. 9 // 10 11 #include "go_asm.h" 12 #include "go_tls.h" 13 #include "textflag.h" 14 #include "cgo/abi_amd64.h" 15 16 #define CLOCK_MONOTONIC $3 17 18 TEXT runtime·settls(SB),NOSPLIT,$0 19 // Nothing to do, pthread already set thread-local storage up. 20 RET 21 22 // mstart_stub is the first function executed on a new thread started by pthread_create. 23 // It just does some low-level setup and then calls mstart. 24 // Note: called with the C calling convention. 25 TEXT runtime·mstart_stub(SB),NOSPLIT,$0 26 // DI points to the m. 27 // We are already on m's g0 stack. 28 29 // Transition from C ABI to Go ABI. 30 PUSH_REGS_HOST_TO_ABI0() 31 32 // Load g and save to TLS entry. 33 // See cmd/link/internal/ld/sym.go:computeTLSOffset. 34 MOVQ m_g0(DI), DX // g 35 MOVQ DX, -8(FS) 36 37 CALL runtime·mstart(SB) 38 39 POP_REGS_HOST_TO_ABI0() 40 41 // Go is all done with this OS thread. 42 // Tell pthread everything is ok (we never join with this thread, so 43 // the value here doesn't really matter). 44 XORL AX, AX 45 RET 46 47 TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 48 MOVQ fn+0(FP), AX 49 MOVL sig+8(FP), DI 50 MOVQ info+16(FP), SI 51 MOVQ ctx+24(FP), DX 52 MOVQ SP, BX // callee-saved 53 ANDQ $~15, SP // alignment for x86_64 ABI 54 CALL AX 55 MOVQ BX, SP 56 RET 57 58 // Called using C ABI. 59 TEXT runtime·sigtramp(SB),NOSPLIT|TOPFRAME|NOFRAME,$0 60 // Transition from C ABI to Go ABI. 61 PUSH_REGS_HOST_TO_ABI0() 62 63 // Set up ABIInternal environment: g in R14, cleared X15. 64 get_tls(R12) 65 MOVQ g(R12), R14 66 PXOR X15, X15 67 68 // Reserve space for spill slots. 69 NOP SP // disable vet stack checking 70 ADJSP $24 71 72 // Call into the Go signal handler 73 MOVQ DI, AX // sig 74 MOVQ SI, BX // info 75 MOVQ DX, CX // ctx 76 CALL ·sigtrampgo<ABIInternal>(SB) 77 78 ADJSP $-24 79 80 POP_REGS_HOST_TO_ABI0() 81 RET 82 83 // 84 // These trampolines help convert from Go calling convention to C calling convention. 85 // They should be called with asmcgocall. 86 // A pointer to the arguments is passed in DI. 87 // A single int32 result is returned in AX. 88 // (For more results, make an args/results structure.) 89 TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0 90 MOVQ 0(DI), DI // arg 1 - attr 91 CALL libc_pthread_attr_init(SB) 92 RET 93 94 TEXT runtime·pthread_attr_destroy_trampoline(SB),NOSPLIT,$0 95 MOVQ 0(DI), DI // arg 1 - attr 96 CALL libc_pthread_attr_destroy(SB) 97 RET 98 99 TEXT runtime·pthread_attr_getstacksize_trampoline(SB),NOSPLIT,$0 100 MOVQ 8(DI), SI // arg 2 - stacksize 101 MOVQ 0(DI), DI // arg 1 - attr 102 CALL libc_pthread_attr_getstacksize(SB) 103 RET 104 105 TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0 106 MOVQ 8(DI), SI // arg 2 - detachstate 107 MOVQ 0(DI), DI // arg 1 - attr 108 CALL libc_pthread_attr_setdetachstate(SB) 109 RET 110 111 TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$16 112 MOVQ 0(DI), SI // arg 2 - attr 113 MOVQ 8(DI), DX // arg 3 - start 114 MOVQ 16(DI), CX // arg 4 - arg 115 MOVQ SP, DI // arg 1 - &thread (discarded) 116 CALL libc_pthread_create(SB) 117 RET 118 119 TEXT runtime·thrkill_trampoline(SB),NOSPLIT,$0 120 MOVL 8(DI), SI // arg 2 - signal 121 MOVQ $0, DX // arg 3 - tcb 122 MOVL 0(DI), DI // arg 1 - tid 123 CALL libc_thrkill(SB) 124 RET 125 126 TEXT runtime·thrsleep_trampoline(SB),NOSPLIT,$0 127 MOVL 8(DI), SI // arg 2 - clock_id 128 MOVQ 16(DI), DX // arg 3 - abstime 129 MOVQ 24(DI), CX // arg 4 - lock 130 MOVQ 32(DI), R8 // arg 5 - abort 131 MOVQ 0(DI), DI // arg 1 - id 132 CALL libc_thrsleep(SB) 133 RET 134 135 TEXT runtime·thrwakeup_trampoline(SB),NOSPLIT,$0 136 MOVL 8(DI), SI // arg 2 - count 137 MOVQ 0(DI), DI // arg 1 - id 138 CALL libc_thrwakeup(SB) 139 RET 140 141 TEXT runtime·exit_trampoline(SB),NOSPLIT,$0 142 MOVL 0(DI), DI // arg 1 exit status 143 CALL libc_exit(SB) 144 MOVL $0xf1, 0xf1 // crash 145 RET 146 147 TEXT runtime·getthrid_trampoline(SB),NOSPLIT,$0 148 MOVQ DI, BX // BX is caller-save 149 CALL libc_getthrid(SB) 150 MOVL AX, 0(BX) // return value 151 RET 152 153 TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$0 154 MOVL 0(DI), BX // signal 155 CALL libc_getpid(SB) 156 MOVL AX, DI // arg 1 pid 157 MOVL BX, SI // arg 2 signal 158 CALL libc_kill(SB) 159 RET 160 161 TEXT runtime·sched_yield_trampoline(SB),NOSPLIT,$0 162 CALL libc_sched_yield(SB) 163 RET 164 165 TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0 166 MOVQ DI, BX 167 MOVQ 0(BX), DI // arg 1 addr 168 MOVQ 8(BX), SI // arg 2 len 169 MOVL 16(BX), DX // arg 3 prot 170 MOVL 20(BX), CX // arg 4 flags 171 MOVL 24(BX), R8 // arg 5 fid 172 MOVL 28(BX), R9 // arg 6 offset 173 CALL libc_mmap(SB) 174 XORL DX, DX 175 CMPQ AX, $-1 176 JNE ok 177 CALL libc_errno(SB) 178 MOVLQSX (AX), DX // errno 179 XORQ AX, AX 180 ok: 181 MOVQ AX, 32(BX) 182 MOVQ DX, 40(BX) 183 RET 184 185 TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0 186 MOVQ 8(DI), SI // arg 2 len 187 MOVQ 0(DI), DI // arg 1 addr 188 CALL libc_munmap(SB) 189 TESTQ AX, AX 190 JEQ 2(PC) 191 MOVL $0xf1, 0xf1 // crash 192 RET 193 194 TEXT runtime·madvise_trampoline(SB), NOSPLIT, $0 195 MOVQ 8(DI), SI // arg 2 len 196 MOVL 16(DI), DX // arg 3 advice 197 MOVQ 0(DI), DI // arg 1 addr 198 CALL libc_madvise(SB) 199 // ignore failure - maybe pages are locked 200 RET 201 202 TEXT runtime·open_trampoline(SB),NOSPLIT,$0 203 MOVL 8(DI), SI // arg 2 - flags 204 MOVL 12(DI), DX // arg 3 - mode 205 MOVQ 0(DI), DI // arg 1 - path 206 XORL AX, AX // vararg: say "no float args" 207 CALL libc_open(SB) 208 RET 209 210 TEXT runtime·close_trampoline(SB),NOSPLIT,$0 211 MOVL 0(DI), DI // arg 1 - fd 212 CALL libc_close(SB) 213 RET 214 215 TEXT runtime·read_trampoline(SB),NOSPLIT,$0 216 MOVQ 8(DI), SI // arg 2 - buf 217 MOVL 16(DI), DX // arg 3 - count 218 MOVL 0(DI), DI // arg 1 - fd 219 CALL libc_read(SB) 220 TESTL AX, AX 221 JGE noerr 222 CALL libc_errno(SB) 223 MOVL (AX), AX // errno 224 NEGL AX // caller expects negative errno value 225 noerr: 226 RET 227 228 TEXT runtime·write_trampoline(SB),NOSPLIT,$0 229 MOVQ 8(DI), SI // arg 2 buf 230 MOVL 16(DI), DX // arg 3 count 231 MOVL 0(DI), DI // arg 1 fd 232 CALL libc_write(SB) 233 TESTL AX, AX 234 JGE noerr 235 CALL libc_errno(SB) 236 MOVL (AX), AX // errno 237 NEGL AX // caller expects negative errno value 238 noerr: 239 RET 240 241 TEXT runtime·pipe2_trampoline(SB),NOSPLIT,$0 242 MOVL 8(DI), SI // arg 2 flags 243 MOVQ 0(DI), DI // arg 1 filedes 244 CALL libc_pipe2(SB) 245 TESTL AX, AX 246 JEQ 3(PC) 247 CALL libc_errno(SB) 248 MOVL (AX), AX // errno 249 NEGL AX // caller expects negative errno value 250 RET 251 252 TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0 253 MOVQ 8(DI), SI // arg 2 new 254 MOVQ 16(DI), DX // arg 3 old 255 MOVL 0(DI), DI // arg 1 which 256 CALL libc_setitimer(SB) 257 RET 258 259 TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0 260 MOVL 0(DI), DI // arg 1 usec 261 CALL libc_usleep(SB) 262 RET 263 264 TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0 265 MOVL 8(DI), SI // arg 2 miblen 266 MOVQ 16(DI), DX // arg 3 out 267 MOVQ 24(DI), CX // arg 4 size 268 MOVQ 32(DI), R8 // arg 5 dst 269 MOVQ 40(DI), R9 // arg 6 ndst 270 MOVQ 0(DI), DI // arg 1 mib 271 CALL libc_sysctl(SB) 272 RET 273 274 TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0 275 CALL libc_kqueue(SB) 276 RET 277 278 TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0 279 MOVQ 8(DI), SI // arg 2 keventt 280 MOVL 16(DI), DX // arg 3 nch 281 MOVQ 24(DI), CX // arg 4 ev 282 MOVL 32(DI), R8 // arg 5 nev 283 MOVQ 40(DI), R9 // arg 6 ts 284 MOVL 0(DI), DI // arg 1 kq 285 CALL libc_kevent(SB) 286 CMPL AX, $-1 287 JNE ok 288 CALL libc_errno(SB) 289 MOVL (AX), AX // errno 290 NEGL AX // caller expects negative errno value 291 ok: 292 RET 293 294 TEXT runtime·clock_gettime_trampoline(SB),NOSPLIT,$0 295 MOVQ 8(DI), SI // arg 2 tp 296 MOVL 0(DI), DI // arg 1 clock_id 297 CALL libc_clock_gettime(SB) 298 TESTL AX, AX 299 JEQ noerr 300 CALL libc_errno(SB) 301 MOVL (AX), AX // errno 302 NEGL AX // caller expects negative errno value 303 noerr: 304 RET 305 306 TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0 307 MOVL 4(DI), SI // arg 2 cmd 308 MOVL 8(DI), DX // arg 3 arg 309 MOVL 0(DI), DI // arg 1 fd 310 XORL AX, AX // vararg: say "no float args" 311 CALL libc_fcntl(SB) 312 RET 313 314 TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$0 315 MOVQ 8(DI), SI // arg 2 new 316 MOVQ 16(DI), DX // arg 3 old 317 MOVL 0(DI), DI // arg 1 sig 318 CALL libc_sigaction(SB) 319 TESTL AX, AX 320 JEQ 2(PC) 321 MOVL $0xf1, 0xf1 // crash 322 RET 323 324 TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$0 325 MOVQ 8(DI), SI // arg 2 new 326 MOVQ 16(DI), DX // arg 3 old 327 MOVL 0(DI), DI // arg 1 how 328 CALL libc_pthread_sigmask(SB) 329 TESTL AX, AX 330 JEQ 2(PC) 331 MOVL $0xf1, 0xf1 // crash 332 RET 333 334 TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0 335 MOVQ 8(DI), SI // arg 2 old 336 MOVQ 0(DI), DI // arg 1 new 337 CALL libc_sigaltstack(SB) 338 TESTQ AX, AX 339 JEQ 2(PC) 340 MOVL $0xf1, 0xf1 // crash 341 RET 342 343 // syscall calls a function in libc on behalf of the syscall package. 344 // syscall takes a pointer to a struct like: 345 // struct { 346 // fn uintptr 347 // a1 uintptr 348 // a2 uintptr 349 // a3 uintptr 350 // r1 uintptr 351 // r2 uintptr 352 // err uintptr 353 // } 354 // syscall must be called on the g0 stack with the 355 // C calling convention (use libcCall). 356 // 357 // syscall expects a 32-bit result and tests for 32-bit -1 358 // to decide there was an error. 359 TEXT runtime·syscall(SB),NOSPLIT,$16 360 MOVQ (0*8)(DI), CX // fn 361 MOVQ (2*8)(DI), SI // a2 362 MOVQ (3*8)(DI), DX // a3 363 MOVQ DI, (SP) 364 MOVQ (1*8)(DI), DI // a1 365 XORL AX, AX // vararg: say "no float args" 366 367 CALL CX 368 369 MOVQ (SP), DI 370 MOVQ AX, (4*8)(DI) // r1 371 MOVQ DX, (5*8)(DI) // r2 372 373 // Standard libc functions return -1 on error 374 // and set errno. 375 CMPL AX, $-1 // Note: high 32 bits are junk 376 JNE ok 377 378 // Get error code from libc. 379 CALL libc_errno(SB) 380 MOVLQSX (AX), AX 381 MOVQ (SP), DI 382 MOVQ AX, (6*8)(DI) // err 383 384 ok: 385 XORL AX, AX // no error (it's ignored anyway) 386 RET 387 388 // syscallX calls a function in libc on behalf of the syscall package. 389 // syscallX takes a pointer to a struct like: 390 // struct { 391 // fn uintptr 392 // a1 uintptr 393 // a2 uintptr 394 // a3 uintptr 395 // r1 uintptr 396 // r2 uintptr 397 // err uintptr 398 // } 399 // syscallX must be called on the g0 stack with the 400 // C calling convention (use libcCall). 401 // 402 // syscallX is like syscall but expects a 64-bit result 403 // and tests for 64-bit -1 to decide there was an error. 404 TEXT runtime·syscallX(SB),NOSPLIT,$16 405 MOVQ (0*8)(DI), CX // fn 406 MOVQ (2*8)(DI), SI // a2 407 MOVQ (3*8)(DI), DX // a3 408 MOVQ DI, (SP) 409 MOVQ (1*8)(DI), DI // a1 410 XORL AX, AX // vararg: say "no float args" 411 412 CALL CX 413 414 MOVQ (SP), DI 415 MOVQ AX, (4*8)(DI) // r1 416 MOVQ DX, (5*8)(DI) // r2 417 418 // Standard libc functions return -1 on error 419 // and set errno. 420 CMPQ AX, $-1 421 JNE ok 422 423 // Get error code from libc. 424 CALL libc_errno(SB) 425 MOVLQSX (AX), AX 426 MOVQ (SP), DI 427 MOVQ AX, (6*8)(DI) // err 428 429 ok: 430 XORL AX, AX // no error (it's ignored anyway) 431 RET 432 433 // syscall6 calls a function in libc on behalf of the syscall package. 434 // syscall6 takes a pointer to a struct like: 435 // struct { 436 // fn uintptr 437 // a1 uintptr 438 // a2 uintptr 439 // a3 uintptr 440 // a4 uintptr 441 // a5 uintptr 442 // a6 uintptr 443 // r1 uintptr 444 // r2 uintptr 445 // err uintptr 446 // } 447 // syscall6 must be called on the g0 stack with the 448 // C calling convention (use libcCall). 449 // 450 // syscall6 expects a 32-bit result and tests for 32-bit -1 451 // to decide there was an error. 452 TEXT runtime·syscall6(SB),NOSPLIT,$16 453 MOVQ (0*8)(DI), R11// fn 454 MOVQ (2*8)(DI), SI // a2 455 MOVQ (3*8)(DI), DX // a3 456 MOVQ (4*8)(DI), CX // a4 457 MOVQ (5*8)(DI), R8 // a5 458 MOVQ (6*8)(DI), R9 // a6 459 MOVQ DI, (SP) 460 MOVQ (1*8)(DI), DI // a1 461 XORL AX, AX // vararg: say "no float args" 462 463 CALL R11 464 465 MOVQ (SP), DI 466 MOVQ AX, (7*8)(DI) // r1 467 MOVQ DX, (8*8)(DI) // r2 468 469 CMPL AX, $-1 470 JNE ok 471 472 CALL libc_errno(SB) 473 MOVLQSX (AX), AX 474 MOVQ (SP), DI 475 MOVQ AX, (9*8)(DI) // err 476 477 ok: 478 XORL AX, AX // no error (it's ignored anyway) 479 RET 480 481 // syscall6X calls a function in libc on behalf of the syscall package. 482 // syscall6X takes a pointer to a struct like: 483 // struct { 484 // fn uintptr 485 // a1 uintptr 486 // a2 uintptr 487 // a3 uintptr 488 // a4 uintptr 489 // a5 uintptr 490 // a6 uintptr 491 // r1 uintptr 492 // r2 uintptr 493 // err uintptr 494 // } 495 // syscall6X must be called on the g0 stack with the 496 // C calling convention (use libcCall). 497 // 498 // syscall6X is like syscall6 but expects a 64-bit result 499 // and tests for 64-bit -1 to decide there was an error. 500 TEXT runtime·syscall6X(SB),NOSPLIT,$16 501 MOVQ (0*8)(DI), R11// fn 502 MOVQ (2*8)(DI), SI // a2 503 MOVQ (3*8)(DI), DX // a3 504 MOVQ (4*8)(DI), CX // a4 505 MOVQ (5*8)(DI), R8 // a5 506 MOVQ (6*8)(DI), R9 // a6 507 MOVQ DI, (SP) 508 MOVQ (1*8)(DI), DI // a1 509 XORL AX, AX // vararg: say "no float args" 510 511 CALL R11 512 513 MOVQ (SP), DI 514 MOVQ AX, (7*8)(DI) // r1 515 MOVQ DX, (8*8)(DI) // r2 516 517 CMPQ AX, $-1 518 JNE ok 519 520 CALL libc_errno(SB) 521 MOVLQSX (AX), AX 522 MOVQ (SP), DI 523 MOVQ AX, (9*8)(DI) // err 524 525 ok: 526 XORL AX, AX // no error (it's ignored anyway) 527 RET 528 529 // syscall10 calls a function in libc on behalf of the syscall package. 530 // syscall10 takes a pointer to a struct like: 531 // struct { 532 // fn uintptr 533 // a1 uintptr 534 // a2 uintptr 535 // a3 uintptr 536 // a4 uintptr 537 // a5 uintptr 538 // a6 uintptr 539 // a7 uintptr 540 // a8 uintptr 541 // a9 uintptr 542 // a10 uintptr 543 // r1 uintptr 544 // r2 uintptr 545 // err uintptr 546 // } 547 // syscall10 must be called on the g0 stack with the 548 // C calling convention (use libcCall). 549 TEXT runtime·syscall10(SB),NOSPLIT,$48 550 // Arguments a1 to a6 get passed in registers, with a7 onwards being 551 // passed via the stack per the x86-64 System V ABI 552 // (https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf). 553 MOVQ (7*8)(DI), R10 // a7 554 MOVQ (8*8)(DI), R11 // a8 555 MOVQ (9*8)(DI), R12 // a9 556 MOVQ (10*8)(DI), R13 // a10 557 MOVQ R10, (0*8)(SP) // a7 558 MOVQ R11, (1*8)(SP) // a8 559 MOVQ R12, (2*8)(SP) // a9 560 MOVQ R13, (3*8)(SP) // a10 561 MOVQ (0*8)(DI), R11 // fn 562 MOVQ (2*8)(DI), SI // a2 563 MOVQ (3*8)(DI), DX // a3 564 MOVQ (4*8)(DI), CX // a4 565 MOVQ (5*8)(DI), R8 // a5 566 MOVQ (6*8)(DI), R9 // a6 567 MOVQ DI, (4*8)(SP) 568 MOVQ (1*8)(DI), DI // a1 569 XORL AX, AX // vararg: say "no float args" 570 571 CALL R11 572 573 MOVQ (4*8)(SP), DI 574 MOVQ AX, (11*8)(DI) // r1 575 MOVQ DX, (12*8)(DI) // r2 576 577 CMPL AX, $-1 578 JNE ok 579 580 CALL libc_errno(SB) 581 MOVLQSX (AX), AX 582 MOVQ (4*8)(SP), DI 583 MOVQ AX, (13*8)(DI) // err 584 585 ok: 586 XORL AX, AX // no error (it's ignored anyway) 587 RET 588 589 // syscall10X calls a function in libc on behalf of the syscall package. 590 // syscall10X takes a pointer to a struct like: 591 // struct { 592 // fn uintptr 593 // a1 uintptr 594 // a2 uintptr 595 // a3 uintptr 596 // a4 uintptr 597 // a5 uintptr 598 // a6 uintptr 599 // a7 uintptr 600 // a8 uintptr 601 // a9 uintptr 602 // a10 uintptr 603 // r1 uintptr 604 // r2 uintptr 605 // err uintptr 606 // } 607 // syscall10X must be called on the g0 stack with the 608 // C calling convention (use libcCall). 609 // 610 // syscall10X is like syscall10 but expects a 64-bit result 611 // and tests for 64-bit -1 to decide there was an error. 612 TEXT runtime·syscall10X(SB),NOSPLIT,$48 613 // Arguments a1 to a6 get passed in registers, with a7 onwards being 614 // passed via the stack per the x86-64 System V ABI 615 // (https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf). 616 MOVQ (7*8)(DI), R10 // a7 617 MOVQ (8*8)(DI), R11 // a8 618 MOVQ (9*8)(DI), R12 // a9 619 MOVQ (10*8)(DI), R13 // a10 620 MOVQ R10, (0*8)(SP) // a7 621 MOVQ R11, (1*8)(SP) // a8 622 MOVQ R12, (2*8)(SP) // a9 623 MOVQ R13, (3*8)(SP) // a10 624 MOVQ (0*8)(DI), R11 // fn 625 MOVQ (2*8)(DI), SI // a2 626 MOVQ (3*8)(DI), DX // a3 627 MOVQ (4*8)(DI), CX // a4 628 MOVQ (5*8)(DI), R8 // a5 629 MOVQ (6*8)(DI), R9 // a6 630 MOVQ DI, (4*8)(SP) 631 MOVQ (1*8)(DI), DI // a1 632 XORL AX, AX // vararg: say "no float args" 633 634 CALL R11 635 636 MOVQ (4*8)(SP), DI 637 MOVQ AX, (11*8)(DI) // r1 638 MOVQ DX, (12*8)(DI) // r2 639 640 CMPQ AX, $-1 641 JNE ok 642 643 CALL libc_errno(SB) 644 MOVLQSX (AX), AX 645 MOVQ (4*8)(SP), DI 646 MOVQ AX, (13*8)(DI) // err 647 648 ok: 649 XORL AX, AX // no error (it's ignored anyway) 650 RET