github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/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 PUSHQ BP 53 MOVQ SP, BP 54 ANDQ $~15, SP // alignment for x86_64 ABI 55 CALL AX 56 MOVQ BP, SP 57 POPQ BP 58 RET 59 60 // Called using C ABI. 61 TEXT runtime·sigtramp(SB),NOSPLIT|TOPFRAME,$0 62 // Transition from C ABI to Go ABI. 63 PUSH_REGS_HOST_TO_ABI0() 64 65 // Set up ABIInternal environment: g in R14, cleared X15. 66 get_tls(R12) 67 MOVQ g(R12), R14 68 PXOR X15, X15 69 70 // Reserve space for spill slots. 71 NOP SP // disable vet stack checking 72 ADJSP $24 73 74 // Call into the Go signal handler 75 MOVQ DI, AX // sig 76 MOVQ SI, BX // info 77 MOVQ DX, CX // ctx 78 CALL ·sigtrampgo<ABIInternal>(SB) 79 80 ADJSP $-24 81 82 POP_REGS_HOST_TO_ABI0() 83 RET 84 85 // 86 // These trampolines help convert from Go calling convention to C calling convention. 87 // They should be called with asmcgocall. 88 // A pointer to the arguments is passed in DI. 89 // A single int32 result is returned in AX. 90 // (For more results, make an args/results structure.) 91 TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0 92 PUSHQ BP 93 MOVQ SP, BP 94 MOVQ 0(DI), DI // arg 1 - attr 95 CALL libc_pthread_attr_init(SB) 96 POPQ BP 97 RET 98 99 TEXT runtime·pthread_attr_destroy_trampoline(SB),NOSPLIT,$0 100 PUSHQ BP 101 MOVQ SP, BP 102 MOVQ 0(DI), DI // arg 1 - attr 103 CALL libc_pthread_attr_destroy(SB) 104 POPQ BP 105 RET 106 107 TEXT runtime·pthread_attr_getstacksize_trampoline(SB),NOSPLIT,$0 108 PUSHQ BP 109 MOVQ SP, BP 110 MOVQ 8(DI), SI // arg 2 - stacksize 111 MOVQ 0(DI), DI // arg 1 - attr 112 CALL libc_pthread_attr_getstacksize(SB) 113 POPQ BP 114 RET 115 116 TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0 117 PUSHQ BP 118 MOVQ SP, BP 119 MOVQ 8(DI), SI // arg 2 - detachstate 120 MOVQ 0(DI), DI // arg 1 - attr 121 CALL libc_pthread_attr_setdetachstate(SB) 122 POPQ BP 123 RET 124 125 TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0 126 PUSHQ BP 127 MOVQ SP, BP 128 SUBQ $16, SP 129 MOVQ 0(DI), SI // arg 2 - attr 130 MOVQ 8(DI), DX // arg 3 - start 131 MOVQ 16(DI), CX // arg 4 - arg 132 MOVQ SP, DI // arg 1 - &thread (discarded) 133 CALL libc_pthread_create(SB) 134 MOVQ BP, SP 135 POPQ BP 136 RET 137 138 TEXT runtime·thrkill_trampoline(SB),NOSPLIT,$0 139 PUSHQ BP 140 MOVQ SP, BP 141 MOVL 8(DI), SI // arg 2 - signal 142 MOVQ $0, DX // arg 3 - tcb 143 MOVL 0(DI), DI // arg 1 - tid 144 CALL libc_thrkill(SB) 145 POPQ BP 146 RET 147 148 TEXT runtime·thrsleep_trampoline(SB),NOSPLIT,$0 149 PUSHQ BP 150 MOVQ SP, BP 151 MOVL 8(DI), SI // arg 2 - clock_id 152 MOVQ 16(DI), DX // arg 3 - abstime 153 MOVQ 24(DI), CX // arg 4 - lock 154 MOVQ 32(DI), R8 // arg 5 - abort 155 MOVQ 0(DI), DI // arg 1 - id 156 CALL libc_thrsleep(SB) 157 POPQ BP 158 RET 159 160 TEXT runtime·thrwakeup_trampoline(SB),NOSPLIT,$0 161 PUSHQ BP 162 MOVQ SP, BP 163 MOVL 8(DI), SI // arg 2 - count 164 MOVQ 0(DI), DI // arg 1 - id 165 CALL libc_thrwakeup(SB) 166 POPQ BP 167 RET 168 169 TEXT runtime·exit_trampoline(SB),NOSPLIT,$0 170 PUSHQ BP 171 MOVQ SP, BP 172 MOVL 0(DI), DI // arg 1 exit status 173 CALL libc_exit(SB) 174 MOVL $0xf1, 0xf1 // crash 175 POPQ BP 176 RET 177 178 TEXT runtime·getthrid_trampoline(SB),NOSPLIT,$0 179 PUSHQ BP 180 MOVQ SP, BP 181 MOVQ DI, BX // BX is caller-save 182 CALL libc_getthrid(SB) 183 MOVL AX, 0(BX) // return value 184 POPQ BP 185 RET 186 187 TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$0 188 PUSHQ BP 189 MOVQ SP, BP 190 MOVL 0(DI), BX // signal 191 CALL libc_getpid(SB) 192 MOVL AX, DI // arg 1 pid 193 MOVL BX, SI // arg 2 signal 194 CALL libc_kill(SB) 195 POPQ BP 196 RET 197 198 TEXT runtime·sched_yield_trampoline(SB),NOSPLIT,$0 199 PUSHQ BP 200 MOVQ SP, BP 201 CALL libc_sched_yield(SB) 202 POPQ BP 203 RET 204 205 TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0 206 PUSHQ BP // make a frame; keep stack aligned 207 MOVQ SP, BP 208 MOVQ DI, BX 209 MOVQ 0(BX), DI // arg 1 addr 210 MOVQ 8(BX), SI // arg 2 len 211 MOVL 16(BX), DX // arg 3 prot 212 MOVL 20(BX), CX // arg 4 flags 213 MOVL 24(BX), R8 // arg 5 fid 214 MOVL 28(BX), R9 // arg 6 offset 215 CALL libc_mmap(SB) 216 XORL DX, DX 217 CMPQ AX, $-1 218 JNE ok 219 CALL libc_errno(SB) 220 MOVLQSX (AX), DX // errno 221 XORQ AX, AX 222 ok: 223 MOVQ AX, 32(BX) 224 MOVQ DX, 40(BX) 225 POPQ BP 226 RET 227 228 TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0 229 PUSHQ BP 230 MOVQ SP, BP 231 MOVQ 8(DI), SI // arg 2 len 232 MOVQ 0(DI), DI // arg 1 addr 233 CALL libc_munmap(SB) 234 TESTQ AX, AX 235 JEQ 2(PC) 236 MOVL $0xf1, 0xf1 // crash 237 POPQ BP 238 RET 239 240 TEXT runtime·madvise_trampoline(SB), NOSPLIT, $0 241 PUSHQ BP 242 MOVQ SP, BP 243 MOVQ 8(DI), SI // arg 2 len 244 MOVL 16(DI), DX // arg 3 advice 245 MOVQ 0(DI), DI // arg 1 addr 246 CALL libc_madvise(SB) 247 // ignore failure - maybe pages are locked 248 POPQ BP 249 RET 250 251 TEXT runtime·open_trampoline(SB),NOSPLIT,$0 252 PUSHQ BP 253 MOVQ SP, BP 254 MOVL 8(DI), SI // arg 2 - flags 255 MOVL 12(DI), DX // arg 3 - mode 256 MOVQ 0(DI), DI // arg 1 - path 257 XORL AX, AX // vararg: say "no float args" 258 CALL libc_open(SB) 259 POPQ BP 260 RET 261 262 TEXT runtime·close_trampoline(SB),NOSPLIT,$0 263 PUSHQ BP 264 MOVQ SP, BP 265 MOVL 0(DI), DI // arg 1 - fd 266 CALL libc_close(SB) 267 POPQ BP 268 RET 269 270 TEXT runtime·read_trampoline(SB),NOSPLIT,$0 271 PUSHQ BP 272 MOVQ SP, BP 273 MOVQ 8(DI), SI // arg 2 - buf 274 MOVL 16(DI), DX // arg 3 - count 275 MOVL 0(DI), DI // arg 1 - fd 276 CALL libc_read(SB) 277 TESTL AX, AX 278 JGE noerr 279 CALL libc_errno(SB) 280 MOVL (AX), AX // errno 281 NEGL AX // caller expects negative errno value 282 noerr: 283 POPQ BP 284 RET 285 286 TEXT runtime·write_trampoline(SB),NOSPLIT,$0 287 PUSHQ BP 288 MOVQ SP, BP 289 MOVQ 8(DI), SI // arg 2 buf 290 MOVL 16(DI), DX // arg 3 count 291 MOVL 0(DI), DI // arg 1 fd 292 CALL libc_write(SB) 293 TESTL AX, AX 294 JGE noerr 295 CALL libc_errno(SB) 296 MOVL (AX), AX // errno 297 NEGL AX // caller expects negative errno value 298 noerr: 299 POPQ BP 300 RET 301 302 TEXT runtime·pipe2_trampoline(SB),NOSPLIT,$0 303 PUSHQ BP 304 MOVQ SP, BP 305 MOVL 8(DI), SI // arg 2 flags 306 MOVQ 0(DI), DI // arg 1 filedes 307 CALL libc_pipe2(SB) 308 TESTL AX, AX 309 JEQ 3(PC) 310 CALL libc_errno(SB) 311 MOVL (AX), AX // errno 312 NEGL AX // caller expects negative errno value 313 POPQ BP 314 RET 315 316 TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0 317 PUSHQ BP 318 MOVQ SP, BP 319 MOVQ 8(DI), SI // arg 2 new 320 MOVQ 16(DI), DX // arg 3 old 321 MOVL 0(DI), DI // arg 1 which 322 CALL libc_setitimer(SB) 323 POPQ BP 324 RET 325 326 TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0 327 PUSHQ BP 328 MOVQ SP, BP 329 MOVL 0(DI), DI // arg 1 usec 330 CALL libc_usleep(SB) 331 POPQ BP 332 RET 333 334 TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0 335 PUSHQ BP 336 MOVQ SP, BP 337 MOVL 8(DI), SI // arg 2 miblen 338 MOVQ 16(DI), DX // arg 3 out 339 MOVQ 24(DI), CX // arg 4 size 340 MOVQ 32(DI), R8 // arg 5 dst 341 MOVQ 40(DI), R9 // arg 6 ndst 342 MOVQ 0(DI), DI // arg 1 mib 343 CALL libc_sysctl(SB) 344 POPQ BP 345 RET 346 347 TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0 348 PUSHQ BP 349 MOVQ SP, BP 350 CALL libc_kqueue(SB) 351 POPQ BP 352 RET 353 354 TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0 355 PUSHQ BP 356 MOVQ SP, BP 357 MOVQ 8(DI), SI // arg 2 keventt 358 MOVL 16(DI), DX // arg 3 nch 359 MOVQ 24(DI), CX // arg 4 ev 360 MOVL 32(DI), R8 // arg 5 nev 361 MOVQ 40(DI), R9 // arg 6 ts 362 MOVL 0(DI), DI // arg 1 kq 363 CALL libc_kevent(SB) 364 CMPL AX, $-1 365 JNE ok 366 CALL libc_errno(SB) 367 MOVL (AX), AX // errno 368 NEGL AX // caller expects negative errno value 369 ok: 370 POPQ BP 371 RET 372 373 TEXT runtime·clock_gettime_trampoline(SB),NOSPLIT,$0 374 PUSHQ BP // make a frame; keep stack aligned 375 MOVQ SP, BP 376 MOVQ 8(DI), SI // arg 2 tp 377 MOVL 0(DI), DI // arg 1 clock_id 378 CALL libc_clock_gettime(SB) 379 TESTL AX, AX 380 JEQ noerr 381 CALL libc_errno(SB) 382 MOVL (AX), AX // errno 383 NEGL AX // caller expects negative errno value 384 noerr: 385 POPQ BP 386 RET 387 388 TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0 389 PUSHQ BP 390 MOVQ SP, BP 391 MOVL 4(DI), SI // arg 2 cmd 392 MOVL 8(DI), DX // arg 3 arg 393 MOVL 0(DI), DI // arg 1 fd 394 XORL AX, AX // vararg: say "no float args" 395 CALL libc_fcntl(SB) 396 POPQ BP 397 RET 398 399 TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$0 400 PUSHQ BP 401 MOVQ SP, BP 402 MOVQ 8(DI), SI // arg 2 new 403 MOVQ 16(DI), DX // arg 3 old 404 MOVL 0(DI), DI // arg 1 sig 405 CALL libc_sigaction(SB) 406 TESTL AX, AX 407 JEQ 2(PC) 408 MOVL $0xf1, 0xf1 // crash 409 POPQ BP 410 RET 411 412 TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$0 413 PUSHQ BP 414 MOVQ SP, BP 415 MOVQ 8(DI), SI // arg 2 new 416 MOVQ 16(DI), DX // arg 3 old 417 MOVL 0(DI), DI // arg 1 how 418 CALL libc_pthread_sigmask(SB) 419 TESTL AX, AX 420 JEQ 2(PC) 421 MOVL $0xf1, 0xf1 // crash 422 POPQ BP 423 RET 424 425 TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0 426 PUSHQ BP 427 MOVQ SP, BP 428 MOVQ 8(DI), SI // arg 2 old 429 MOVQ 0(DI), DI // arg 1 new 430 CALL libc_sigaltstack(SB) 431 TESTQ AX, AX 432 JEQ 2(PC) 433 MOVL $0xf1, 0xf1 // crash 434 POPQ BP 435 RET 436 437 // syscall calls a function in libc on behalf of the syscall package. 438 // syscall takes a pointer to a struct like: 439 // struct { 440 // fn uintptr 441 // a1 uintptr 442 // a2 uintptr 443 // a3 uintptr 444 // r1 uintptr 445 // r2 uintptr 446 // err uintptr 447 // } 448 // syscall must be called on the g0 stack with the 449 // C calling convention (use libcCall). 450 // 451 // syscall expects a 32-bit result and tests for 32-bit -1 452 // to decide there was an error. 453 TEXT runtime·syscall(SB),NOSPLIT,$0 454 PUSHQ BP 455 MOVQ SP, BP 456 SUBQ $16, SP 457 MOVQ (0*8)(DI), CX // fn 458 MOVQ (2*8)(DI), SI // a2 459 MOVQ (3*8)(DI), DX // a3 460 MOVQ DI, (SP) 461 MOVQ (1*8)(DI), DI // a1 462 XORL AX, AX // vararg: say "no float args" 463 464 CALL CX 465 466 MOVQ (SP), DI 467 MOVQ AX, (4*8)(DI) // r1 468 MOVQ DX, (5*8)(DI) // r2 469 470 // Standard libc functions return -1 on error 471 // and set errno. 472 CMPL AX, $-1 // Note: high 32 bits are junk 473 JNE ok 474 475 // Get error code from libc. 476 CALL libc_errno(SB) 477 MOVLQSX (AX), AX 478 MOVQ (SP), DI 479 MOVQ AX, (6*8)(DI) // err 480 481 ok: 482 XORL AX, AX // no error (it's ignored anyway) 483 MOVQ BP, SP 484 POPQ BP 485 RET 486 487 // syscallX calls a function in libc on behalf of the syscall package. 488 // syscallX takes a pointer to a struct like: 489 // struct { 490 // fn uintptr 491 // a1 uintptr 492 // a2 uintptr 493 // a3 uintptr 494 // r1 uintptr 495 // r2 uintptr 496 // err uintptr 497 // } 498 // syscallX must be called on the g0 stack with the 499 // C calling convention (use libcCall). 500 // 501 // syscallX is like syscall but expects a 64-bit result 502 // and tests for 64-bit -1 to decide there was an error. 503 TEXT runtime·syscallX(SB),NOSPLIT,$0 504 PUSHQ BP 505 MOVQ SP, BP 506 SUBQ $16, SP 507 MOVQ (0*8)(DI), CX // fn 508 MOVQ (2*8)(DI), SI // a2 509 MOVQ (3*8)(DI), DX // a3 510 MOVQ DI, (SP) 511 MOVQ (1*8)(DI), DI // a1 512 XORL AX, AX // vararg: say "no float args" 513 514 CALL CX 515 516 MOVQ (SP), DI 517 MOVQ AX, (4*8)(DI) // r1 518 MOVQ DX, (5*8)(DI) // r2 519 520 // Standard libc functions return -1 on error 521 // and set errno. 522 CMPQ AX, $-1 523 JNE ok 524 525 // Get error code from libc. 526 CALL libc_errno(SB) 527 MOVLQSX (AX), AX 528 MOVQ (SP), DI 529 MOVQ AX, (6*8)(DI) // err 530 531 ok: 532 XORL AX, AX // no error (it's ignored anyway) 533 MOVQ BP, SP 534 POPQ BP 535 RET 536 537 // syscall6 calls a function in libc on behalf of the syscall package. 538 // syscall6 takes a pointer to a struct like: 539 // struct { 540 // fn uintptr 541 // a1 uintptr 542 // a2 uintptr 543 // a3 uintptr 544 // a4 uintptr 545 // a5 uintptr 546 // a6 uintptr 547 // r1 uintptr 548 // r2 uintptr 549 // err uintptr 550 // } 551 // syscall6 must be called on the g0 stack with the 552 // C calling convention (use libcCall). 553 // 554 // syscall6 expects a 32-bit result and tests for 32-bit -1 555 // to decide there was an error. 556 TEXT runtime·syscall6(SB),NOSPLIT,$0 557 PUSHQ BP 558 MOVQ SP, BP 559 SUBQ $16, SP 560 MOVQ (0*8)(DI), R11// fn 561 MOVQ (2*8)(DI), SI // a2 562 MOVQ (3*8)(DI), DX // a3 563 MOVQ (4*8)(DI), CX // a4 564 MOVQ (5*8)(DI), R8 // a5 565 MOVQ (6*8)(DI), R9 // a6 566 MOVQ DI, (SP) 567 MOVQ (1*8)(DI), DI // a1 568 XORL AX, AX // vararg: say "no float args" 569 570 CALL R11 571 572 MOVQ (SP), DI 573 MOVQ AX, (7*8)(DI) // r1 574 MOVQ DX, (8*8)(DI) // r2 575 576 CMPL AX, $-1 577 JNE ok 578 579 CALL libc_errno(SB) 580 MOVLQSX (AX), AX 581 MOVQ (SP), DI 582 MOVQ AX, (9*8)(DI) // err 583 584 ok: 585 XORL AX, AX // no error (it's ignored anyway) 586 MOVQ BP, SP 587 POPQ BP 588 RET 589 590 // syscall6X calls a function in libc on behalf of the syscall package. 591 // syscall6X takes a pointer to a struct like: 592 // struct { 593 // fn uintptr 594 // a1 uintptr 595 // a2 uintptr 596 // a3 uintptr 597 // a4 uintptr 598 // a5 uintptr 599 // a6 uintptr 600 // r1 uintptr 601 // r2 uintptr 602 // err uintptr 603 // } 604 // syscall6X must be called on the g0 stack with the 605 // C calling convention (use libcCall). 606 // 607 // syscall6X is like syscall6 but expects a 64-bit result 608 // and tests for 64-bit -1 to decide there was an error. 609 TEXT runtime·syscall6X(SB),NOSPLIT,$0 610 PUSHQ BP 611 MOVQ SP, BP 612 SUBQ $16, SP 613 MOVQ (0*8)(DI), R11// fn 614 MOVQ (2*8)(DI), SI // a2 615 MOVQ (3*8)(DI), DX // a3 616 MOVQ (4*8)(DI), CX // a4 617 MOVQ (5*8)(DI), R8 // a5 618 MOVQ (6*8)(DI), R9 // a6 619 MOVQ DI, (SP) 620 MOVQ (1*8)(DI), DI // a1 621 XORL AX, AX // vararg: say "no float args" 622 623 CALL R11 624 625 MOVQ (SP), DI 626 MOVQ AX, (7*8)(DI) // r1 627 MOVQ DX, (8*8)(DI) // r2 628 629 CMPQ AX, $-1 630 JNE ok 631 632 CALL libc_errno(SB) 633 MOVLQSX (AX), AX 634 MOVQ (SP), DI 635 MOVQ AX, (9*8)(DI) // err 636 637 ok: 638 XORL AX, AX // no error (it's ignored anyway) 639 MOVQ BP, SP 640 POPQ BP 641 RET 642 643 // syscall10 calls a function in libc on behalf of the syscall package. 644 // syscall10 takes a pointer to a struct like: 645 // struct { 646 // fn uintptr 647 // a1 uintptr 648 // a2 uintptr 649 // a3 uintptr 650 // a4 uintptr 651 // a5 uintptr 652 // a6 uintptr 653 // a7 uintptr 654 // a8 uintptr 655 // a9 uintptr 656 // a10 uintptr 657 // r1 uintptr 658 // r2 uintptr 659 // err uintptr 660 // } 661 // syscall10 must be called on the g0 stack with the 662 // C calling convention (use libcCall). 663 TEXT runtime·syscall10(SB),NOSPLIT,$0 664 PUSHQ BP 665 MOVQ SP, BP 666 SUBQ $48, SP 667 668 // Arguments a1 to a6 get passed in registers, with a7 onwards being 669 // passed via the stack per the x86-64 System V ABI 670 // (https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf). 671 MOVQ (7*8)(DI), R10 // a7 672 MOVQ (8*8)(DI), R11 // a8 673 MOVQ (9*8)(DI), R12 // a9 674 MOVQ (10*8)(DI), R13 // a10 675 MOVQ R10, (0*8)(SP) // a7 676 MOVQ R11, (1*8)(SP) // a8 677 MOVQ R12, (2*8)(SP) // a9 678 MOVQ R13, (3*8)(SP) // a10 679 MOVQ (0*8)(DI), R11 // fn 680 MOVQ (2*8)(DI), SI // a2 681 MOVQ (3*8)(DI), DX // a3 682 MOVQ (4*8)(DI), CX // a4 683 MOVQ (5*8)(DI), R8 // a5 684 MOVQ (6*8)(DI), R9 // a6 685 MOVQ DI, (4*8)(SP) 686 MOVQ (1*8)(DI), DI // a1 687 XORL AX, AX // vararg: say "no float args" 688 689 CALL R11 690 691 MOVQ (4*8)(SP), DI 692 MOVQ AX, (11*8)(DI) // r1 693 MOVQ DX, (12*8)(DI) // r2 694 695 CMPL AX, $-1 696 JNE ok 697 698 CALL libc_errno(SB) 699 MOVLQSX (AX), AX 700 MOVQ (4*8)(SP), DI 701 MOVQ AX, (13*8)(DI) // err 702 703 ok: 704 XORL AX, AX // no error (it's ignored anyway) 705 MOVQ BP, SP 706 POPQ BP 707 RET 708 709 // syscall10X calls a function in libc on behalf of the syscall package. 710 // syscall10X takes a pointer to a struct like: 711 // struct { 712 // fn uintptr 713 // a1 uintptr 714 // a2 uintptr 715 // a3 uintptr 716 // a4 uintptr 717 // a5 uintptr 718 // a6 uintptr 719 // a7 uintptr 720 // a8 uintptr 721 // a9 uintptr 722 // a10 uintptr 723 // r1 uintptr 724 // r2 uintptr 725 // err uintptr 726 // } 727 // syscall10X must be called on the g0 stack with the 728 // C calling convention (use libcCall). 729 // 730 // syscall10X is like syscall10 but expects a 64-bit result 731 // and tests for 64-bit -1 to decide there was an error. 732 TEXT runtime·syscall10X(SB),NOSPLIT,$0 733 PUSHQ BP 734 MOVQ SP, BP 735 SUBQ $48, SP 736 737 // Arguments a1 to a6 get passed in registers, with a7 onwards being 738 // passed via the stack per the x86-64 System V ABI 739 // (https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf). 740 MOVQ (7*8)(DI), R10 // a7 741 MOVQ (8*8)(DI), R11 // a8 742 MOVQ (9*8)(DI), R12 // a9 743 MOVQ (10*8)(DI), R13 // a10 744 MOVQ R10, (0*8)(SP) // a7 745 MOVQ R11, (1*8)(SP) // a8 746 MOVQ R12, (2*8)(SP) // a9 747 MOVQ R13, (3*8)(SP) // a10 748 MOVQ (0*8)(DI), R11 // fn 749 MOVQ (2*8)(DI), SI // a2 750 MOVQ (3*8)(DI), DX // a3 751 MOVQ (4*8)(DI), CX // a4 752 MOVQ (5*8)(DI), R8 // a5 753 MOVQ (6*8)(DI), R9 // a6 754 MOVQ DI, (4*8)(SP) 755 MOVQ (1*8)(DI), DI // a1 756 XORL AX, AX // vararg: say "no float args" 757 758 CALL R11 759 760 MOVQ (4*8)(SP), DI 761 MOVQ AX, (11*8)(DI) // r1 762 MOVQ DX, (12*8)(DI) // r2 763 764 CMPQ AX, $-1 765 JNE ok 766 767 CALL libc_errno(SB) 768 MOVLQSX (AX), AX 769 MOVQ (4*8)(SP), DI 770 MOVQ AX, (13*8)(DI) // err 771 772 ok: 773 XORL AX, AX // no error (it's ignored anyway) 774 MOVQ BP, SP 775 POPQ BP 776 RET