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