github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/runtime/sys_openbsd_arm64.s (about)

     1  // Copyright 2019 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 arm64, 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_arm64.h"
    15  
    16  #define CLOCK_REALTIME	$0
    17  #define	CLOCK_MONOTONIC	$3
    18  
    19  // mstart_stub is the first function executed on a new thread started by pthread_create.
    20  // It just does some low-level setup and then calls mstart.
    21  // Note: called with the C calling convention.
    22  TEXT runtime·mstart_stub(SB),NOSPLIT,$144
    23  	// R0 points to the m.
    24  	// We are already on m's g0 stack.
    25  
    26  	// Save callee-save registers.
    27  	SAVE_R19_TO_R28(8)
    28  	SAVE_F8_TO_F15(88)
    29  
    30  	MOVD    m_g0(R0), g
    31  	BL	runtime·save_g(SB)
    32  
    33  	BL	runtime·mstart(SB)
    34  
    35  	// Restore callee-save registers.
    36  	RESTORE_R19_TO_R28(8)
    37  	RESTORE_F8_TO_F15(88)
    38  
    39  	// Go is all done with this OS thread.
    40  	// Tell pthread everything is ok (we never join with this thread, so
    41  	// the value here doesn't really matter).
    42  	MOVD	$0, R0
    43  
    44  	RET
    45  
    46  TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
    47  	MOVW	sig+8(FP), R0
    48  	MOVD	info+16(FP), R1
    49  	MOVD	ctx+24(FP), R2
    50  	MOVD	fn+0(FP), R11
    51  	BL	(R11)			// Alignment for ELF ABI?
    52  	RET
    53  
    54  TEXT runtime·sigtramp(SB),NOSPLIT|TOPFRAME,$192
    55  	// Save callee-save registers in the case of signal forwarding.
    56  	// Please refer to https://golang.org/issue/31827 .
    57  	SAVE_R19_TO_R28(8*4)
    58  	SAVE_F8_TO_F15(8*14)
    59  
    60  	// If called from an external code context, g will not be set.
    61  	// Save R0, since runtime·load_g will clobber it.
    62  	MOVW	R0, 8(RSP)		// signum
    63  	BL	runtime·load_g(SB)
    64  
    65  	// Restore signum to R0.
    66  	MOVW	8(RSP), R0
    67  	// R1 and R2 already contain info and ctx, respectively.
    68  	BL	runtime·sigtrampgo<ABIInternal>(SB)
    69  
    70  	// Restore callee-save registers.
    71  	RESTORE_R19_TO_R28(8*4)
    72  	RESTORE_F8_TO_F15(8*14)
    73  
    74  	RET
    75  
    76  //
    77  // These trampolines help convert from Go calling convention to C calling convention.
    78  // They should be called with asmcgocall.
    79  // A pointer to the arguments is passed in R0.
    80  // A single int32 result is returned in R0.
    81  // (For more results, make an args/results structure.)
    82  TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0
    83  	MOVD	0(R0), R0		// arg 1 - attr
    84  	CALL	libc_pthread_attr_init(SB)
    85  	RET
    86  
    87  TEXT runtime·pthread_attr_destroy_trampoline(SB),NOSPLIT,$0
    88  	MOVD	0(R0), R0		// arg 1 - attr
    89  	CALL	libc_pthread_attr_destroy(SB)
    90  	RET
    91  
    92  TEXT runtime·pthread_attr_getstacksize_trampoline(SB),NOSPLIT,$0
    93  	MOVD	8(R0), R1		// arg 2 - size
    94  	MOVD	0(R0), R0		// arg 1 - attr
    95  	CALL	libc_pthread_attr_getstacksize(SB)
    96  	RET
    97  
    98  TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0
    99  	MOVD	8(R0), R1		// arg 2 - state
   100  	MOVD	0(R0), R0		// arg 1 - attr
   101  	CALL	libc_pthread_attr_setdetachstate(SB)
   102  	RET
   103  
   104  TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0
   105  	MOVD	0(R0), R1		// arg 2 - attr
   106  	MOVD	8(R0), R2		// arg 3 - start
   107  	MOVD	16(R0), R3		// arg 4 - arg
   108  	SUB	$16, RSP
   109  	MOVD	RSP, R0			// arg 1 - &threadid (discard)
   110  	CALL	libc_pthread_create(SB)
   111  	ADD	$16, RSP
   112  	RET
   113  
   114  TEXT runtime·thrkill_trampoline(SB),NOSPLIT,$0
   115  	MOVW	8(R0), R1		// arg 2 - signal
   116  	MOVD	$0, R2			// arg 3 - tcb
   117  	MOVW	0(R0), R0		// arg 1 - tid
   118  	CALL	libc_thrkill(SB)
   119  	RET
   120  
   121  TEXT runtime·thrsleep_trampoline(SB),NOSPLIT,$0
   122  	MOVW	8(R0), R1		// arg 2 - clock_id
   123  	MOVD	16(R0), R2		// arg 3 - abstime
   124  	MOVD	24(R0), R3		// arg 4 - lock
   125  	MOVD	32(R0), R4		// arg 5 - abort
   126  	MOVD	0(R0), R0		// arg 1 - id
   127  	CALL	libc_thrsleep(SB)
   128  	RET
   129  
   130  TEXT runtime·thrwakeup_trampoline(SB),NOSPLIT,$0
   131  	MOVW	8(R0), R1		// arg 2 - count
   132  	MOVD	0(R0), R0		// arg 1 - id
   133  	CALL	libc_thrwakeup(SB)
   134  	RET
   135  
   136  TEXT runtime·exit_trampoline(SB),NOSPLIT,$0
   137  	MOVW	0(R0), R0		// arg 1 - status
   138  	CALL	libc_exit(SB)
   139  	MOVD	$0, R0			// crash on failure
   140  	MOVD	R0, (R0)
   141  	RET
   142  
   143  TEXT runtime·getthrid_trampoline(SB),NOSPLIT,$0
   144  	MOVD	R0, R19			// pointer to args
   145  	CALL	libc_getthrid(SB)
   146  	MOVW	R0, 0(R19)		// return value
   147  	RET
   148  
   149  TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$0
   150  	MOVD	R0, R19			// pointer to args
   151  	CALL	libc_getpid(SB)		// arg 1 - pid
   152  	MOVW	0(R19), R1		// arg 2 - signal
   153  	CALL	libc_kill(SB)
   154  	RET
   155  
   156  TEXT runtime·sched_yield_trampoline(SB),NOSPLIT,$0
   157  	CALL	libc_sched_yield(SB)
   158  	RET
   159  
   160  TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
   161  	MOVD    R0, R19			// pointer to args
   162  	MOVD	0(R19), R0		// arg 1 - addr
   163  	MOVD	8(R19), R1		// arg 2 - len
   164  	MOVW	16(R19), R2		// arg 3 - prot
   165  	MOVW	20(R19), R3		// arg 4 - flags
   166  	MOVW	24(R19), R4		// arg 5 - fid
   167  	MOVW	28(R19), R5		// arg 6 - offset
   168  	CALL	libc_mmap(SB)
   169  	MOVD	$0, R1
   170  	CMP	$-1, R0
   171  	BNE	noerr
   172  	CALL	libc_errno(SB)
   173  	MOVW	(R0), R1		// errno
   174  	MOVD	$0, R0
   175  noerr:
   176  	MOVD	R0, 32(R19)
   177  	MOVD	R1, 40(R19)
   178  	RET
   179  
   180  TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0
   181  	MOVD	8(R0), R1		// arg 2 - len
   182  	MOVD	0(R0), R0		// arg 1 - addr
   183  	CALL	libc_munmap(SB)
   184  	CMP	$-1, R0
   185  	BNE	3(PC)
   186  	MOVD	$0, R0			// crash on failure
   187  	MOVD	R0, (R0)
   188  	RET
   189  
   190  TEXT runtime·madvise_trampoline(SB), NOSPLIT, $0
   191  	MOVD	8(R0), R1		// arg 2 - len
   192  	MOVW	16(R0), R2		// arg 3 - advice
   193  	MOVD	0(R0), R0		// arg 1 - addr
   194  	CALL	libc_madvise(SB)
   195  	// ignore failure - maybe pages are locked
   196  	RET
   197  
   198  TEXT runtime·open_trampoline(SB),NOSPLIT,$0
   199  	MOVW	8(R0), R1		// arg 2 - flags
   200  	MOVW	12(R0), R2		// arg 3 - mode
   201  	MOVD	0(R0), R0		// arg 1 - path
   202  	MOVD	$0, R3			// varargs
   203  	CALL	libc_open(SB)
   204  	RET
   205  
   206  TEXT runtime·close_trampoline(SB),NOSPLIT,$0
   207  	MOVD	0(R0), R0		// arg 1 - fd
   208  	CALL	libc_close(SB)
   209  	RET
   210  
   211  TEXT runtime·read_trampoline(SB),NOSPLIT,$0
   212  	MOVD	8(R0), R1		// arg 2 - buf
   213  	MOVW	16(R0), R2		// arg 3 - count
   214  	MOVW	0(R0), R0		// arg 1 - fd
   215  	CALL	libc_read(SB)
   216  	CMP	$-1, R0
   217  	BNE	noerr
   218  	CALL	libc_errno(SB)
   219  	MOVW	(R0), R0		// errno
   220  	NEG	R0, R0			// caller expects negative errno value
   221  noerr:
   222  	RET
   223  
   224  TEXT runtime·write_trampoline(SB),NOSPLIT,$0
   225  	MOVD	8(R0), R1		// arg 2 - buf
   226  	MOVW	16(R0), R2		// arg 3 - count
   227  	MOVW	0(R0), R0		// arg 1 - fd
   228  	CALL	libc_write(SB)
   229  	CMP	$-1, R0
   230  	BNE	noerr
   231  	CALL	libc_errno(SB)
   232  	MOVW	(R0), R0		// errno
   233  	NEG	R0, R0			// caller expects negative errno value
   234  noerr:
   235  	RET
   236  
   237  TEXT runtime·pipe2_trampoline(SB),NOSPLIT,$0
   238  	MOVW	8(R0), R1		// arg 2 - flags
   239  	MOVD	0(R0), R0		// arg 1 - filedes
   240  	CALL	libc_pipe2(SB)
   241  	CMP	$-1, R0
   242  	BNE	noerr
   243  	CALL	libc_errno(SB)
   244  	MOVW	(R0), R0		// errno
   245  	NEG	R0, R0			// caller expects negative errno value
   246  noerr:
   247  	RET
   248  
   249  TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0
   250  	MOVD	8(R0), R1		// arg 2 - new
   251  	MOVD	16(R0), R2		// arg 3 - old
   252  	MOVW	0(R0), R0		// arg 1 - which
   253  	CALL	libc_setitimer(SB)
   254  	RET
   255  
   256  TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0
   257  	MOVD	0(R0), R0		// arg 1 - usec
   258  	CALL	libc_usleep(SB)
   259  	RET
   260  
   261  TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0
   262  	MOVW	8(R0), R1		// arg 2 - miblen
   263  	MOVD	16(R0), R2		// arg 3 - out
   264  	MOVD	24(R0), R3		// arg 4 - size
   265  	MOVD	32(R0), R4		// arg 5 - dst
   266  	MOVD	40(R0), R5		// arg 6 - ndst
   267  	MOVD	0(R0), R0		// arg 1 - mib
   268  	CALL	libc_sysctl(SB)
   269  	RET
   270  
   271  TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0
   272  	CALL	libc_kqueue(SB)
   273  	RET
   274  
   275  TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0
   276  	MOVD	8(R0), R1		// arg 2 - keventt
   277  	MOVW	16(R0), R2		// arg 3 - nch
   278  	MOVD	24(R0), R3		// arg 4 - ev
   279  	MOVW	32(R0), R4		// arg 5 - nev
   280  	MOVD	40(R0), R5		// arg 6 - ts
   281  	MOVW	0(R0), R0		// arg 1 - kq
   282  	CALL	libc_kevent(SB)
   283  	CMP	$-1, R0
   284  	BNE	noerr
   285  	CALL	libc_errno(SB)
   286  	MOVW	(R0), R0		// errno
   287  	NEG	R0, R0			// caller expects negative errno value
   288  noerr:
   289  	RET
   290  
   291  TEXT runtime·clock_gettime_trampoline(SB),NOSPLIT,$0
   292  	MOVD	8(R0), R1		// arg 2 - tp
   293  	MOVD	0(R0), R0		// arg 1 - clock_id
   294  	CALL	libc_clock_gettime(SB)
   295  	CMP	$-1, R0
   296  	BNE	noerr
   297  	CALL	libc_errno(SB)
   298  	MOVW	(R0), R0		// errno
   299  	NEG	R0, R0			// caller expects negative errno value
   300  noerr:
   301  	RET
   302  
   303  TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0
   304  	MOVW	4(R0), R1		// arg 2 - cmd
   305  	MOVW	8(R0), R2		// arg 3 - arg
   306  	MOVW	0(R0), R0		// arg 1 - fd
   307  	MOVD	$0, R3			// vararg
   308  	CALL	libc_fcntl(SB)
   309  	RET
   310  
   311  TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$0
   312  	MOVD	8(R0), R1		// arg 2 - new
   313  	MOVD	16(R0), R2		// arg 3 - old
   314  	MOVW	0(R0), R0		// arg 1 - sig
   315  	CALL	libc_sigaction(SB)
   316  	CMP	$-1, R0
   317  	BNE	3(PC)
   318  	MOVD	$0, R0			// crash on syscall failure
   319  	MOVD	R0, (R0)
   320  	RET
   321  
   322  TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$0
   323  	MOVD	8(R0), R1		// arg 2 - new
   324  	MOVD	16(R0), R2		// arg 3 - old
   325  	MOVW	0(R0), R0		// arg 1 - how
   326  	CALL	libc_pthread_sigmask(SB)
   327  	CMP	$-1, R0
   328  	BNE	3(PC)
   329  	MOVD	$0, R0			// crash on syscall failure
   330  	MOVD	R0, (R0)
   331  	RET
   332  
   333  TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
   334  	MOVD	8(R0), R1		// arg 2 - old
   335  	MOVD	0(R0), R0		// arg 1 - new
   336  	CALL	libc_sigaltstack(SB)
   337  	CMP	$-1, R0
   338  	BNE	3(PC)
   339  	MOVD	$0, R0			// crash on syscall failure
   340  	MOVD	R0, (R0)
   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,$0
   360  	MOVD    R0, R19			// pointer to args
   361  
   362  	MOVD	(0*8)(R19), R11		// fn
   363  	MOVD	(1*8)(R19), R0		// a1
   364  	MOVD	(2*8)(R19), R1		// a2
   365  	MOVD	(3*8)(R19), R2		// a3
   366  	MOVD	$0, R3			// vararg
   367  
   368  	CALL	R11
   369  
   370  	MOVD	R0, (4*8)(R19)		// r1
   371  	MOVD	R1, (5*8)(R19)		// r2
   372  
   373  	// Standard libc functions return -1 on error
   374  	// and set errno.
   375  	CMPW	$-1, R0
   376  	BNE	ok
   377  
   378  	// Get error code from libc.
   379  	CALL	libc_errno(SB)
   380  	MOVW	(R0), R0
   381  	MOVD	R0, (6*8)(R19)		// err
   382  
   383  ok:
   384  	RET
   385  
   386  // syscallX calls a function in libc on behalf of the syscall package.
   387  // syscallX takes a pointer to a struct like:
   388  // struct {
   389  //	fn    uintptr
   390  //	a1    uintptr
   391  //	a2    uintptr
   392  //	a3    uintptr
   393  //	r1    uintptr
   394  //	r2    uintptr
   395  //	err   uintptr
   396  // }
   397  // syscallX must be called on the g0 stack with the
   398  // C calling convention (use libcCall).
   399  //
   400  // syscallX is like syscall but expects a 64-bit result
   401  // and tests for 64-bit -1 to decide there was an error.
   402  TEXT runtime·syscallX(SB),NOSPLIT,$0
   403  	MOVD    R0, R19			// pointer to args
   404  
   405  	MOVD	(0*8)(R19), R11		// fn
   406  	MOVD	(1*8)(R19), R0		// a1
   407  	MOVD	(2*8)(R19), R1		// a2
   408  	MOVD	(3*8)(R19), R2		// a3
   409  	MOVD	$0, R3			// vararg
   410  
   411  	CALL	R11
   412  
   413  	MOVD	R0, (4*8)(R19)		// r1
   414  	MOVD	R1, (5*8)(R19)		// r2
   415  
   416  	// Standard libc functions return -1 on error
   417  	// and set errno.
   418  	CMP	$-1, R0
   419  	BNE	ok
   420  
   421  	// Get error code from libc.
   422  	CALL	libc_errno(SB)
   423  	MOVW	(R0), R0
   424  	MOVD	R0, (6*8)(R19)		// err
   425  
   426  ok:
   427  	RET
   428  
   429  // syscall6 calls a function in libc on behalf of the syscall package.
   430  // syscall6 takes a pointer to a struct like:
   431  // struct {
   432  //	fn    uintptr
   433  //	a1    uintptr
   434  //	a2    uintptr
   435  //	a3    uintptr
   436  //	a4    uintptr
   437  //	a5    uintptr
   438  //	a6    uintptr
   439  //	r1    uintptr
   440  //	r2    uintptr
   441  //	err   uintptr
   442  // }
   443  // syscall6 must be called on the g0 stack with the
   444  // C calling convention (use libcCall).
   445  //
   446  // syscall6 expects a 32-bit result and tests for 32-bit -1
   447  // to decide there was an error.
   448  TEXT runtime·syscall6(SB),NOSPLIT,$0
   449  	MOVD    R0, R19			// pointer to args
   450  
   451  	MOVD	(0*8)(R19), R11		// fn
   452  	MOVD	(1*8)(R19), R0		// a1
   453  	MOVD	(2*8)(R19), R1		// a2
   454  	MOVD	(3*8)(R19), R2		// a3
   455  	MOVD	(4*8)(R19), R3		// a4
   456  	MOVD	(5*8)(R19), R4		// a5
   457  	MOVD	(6*8)(R19), R5		// a6
   458  	MOVD	$0, R6			// vararg
   459  
   460  	CALL	R11
   461  
   462  	MOVD	R0, (7*8)(R19)		// r1
   463  	MOVD	R1, (8*8)(R19)		// r2
   464  
   465  	// Standard libc functions return -1 on error
   466  	// and set errno.
   467  	CMPW	$-1, R0
   468  	BNE	ok
   469  
   470  	// Get error code from libc.
   471  	CALL	libc_errno(SB)
   472  	MOVW	(R0), R0
   473  	MOVD	R0, (9*8)(R19)		// err
   474  
   475  ok:
   476  	RET
   477  
   478  // syscall6X calls a function in libc on behalf of the syscall package.
   479  // syscall6X takes a pointer to a struct like:
   480  // struct {
   481  //	fn    uintptr
   482  //	a1    uintptr
   483  //	a2    uintptr
   484  //	a3    uintptr
   485  //	a4    uintptr
   486  //	a5    uintptr
   487  //	a6    uintptr
   488  //	r1    uintptr
   489  //	r2    uintptr
   490  //	err   uintptr
   491  // }
   492  // syscall6X must be called on the g0 stack with the
   493  // C calling convention (use libcCall).
   494  //
   495  // syscall6X is like syscall6 but expects a 64-bit result
   496  // and tests for 64-bit -1 to decide there was an error.
   497  TEXT runtime·syscall6X(SB),NOSPLIT,$0
   498  	MOVD    R0, R19			// pointer to args
   499  
   500  	MOVD	(0*8)(R19), R11		// fn
   501  	MOVD	(1*8)(R19), R0		// a1
   502  	MOVD	(2*8)(R19), R1		// a2
   503  	MOVD	(3*8)(R19), R2		// a3
   504  	MOVD	(4*8)(R19), R3		// a4
   505  	MOVD	(5*8)(R19), R4		// a5
   506  	MOVD	(6*8)(R19), R5		// a6
   507  	MOVD	$0, R6			// vararg
   508  
   509  	CALL	R11
   510  
   511  	MOVD	R0, (7*8)(R19)		// r1
   512  	MOVD	R1, (8*8)(R19)		// r2
   513  
   514  	// Standard libc functions return -1 on error
   515  	// and set errno.
   516  	CMP	$-1, R0
   517  	BNE	ok
   518  
   519  	// Get error code from libc.
   520  	CALL	libc_errno(SB)
   521  	MOVW	(R0), R0
   522  	MOVD	R0, (9*8)(R19)		// err
   523  
   524  ok:
   525  	RET
   526  
   527  // syscall10 calls a function in libc on behalf of the syscall package.
   528  // syscall10 takes a pointer to a struct like:
   529  // struct {
   530  //	fn    uintptr
   531  //	a1    uintptr
   532  //	a2    uintptr
   533  //	a3    uintptr
   534  //	a4    uintptr
   535  //	a5    uintptr
   536  //	a6    uintptr
   537  //	a7    uintptr
   538  //	a8    uintptr
   539  //	a9    uintptr
   540  //	a10   uintptr
   541  //	r1    uintptr
   542  //	r2    uintptr
   543  //	err   uintptr
   544  // }
   545  // syscall10 must be called on the g0 stack with the
   546  // C calling convention (use libcCall).
   547  TEXT runtime·syscall10(SB),NOSPLIT,$0
   548  	MOVD    R0, R19			// pointer to args
   549  
   550  	MOVD	(0*8)(R19), R11		// fn
   551  	MOVD	(1*8)(R19), R0		// a1
   552  	MOVD	(2*8)(R19), R1		// a2
   553  	MOVD	(3*8)(R19), R2		// a3
   554  	MOVD	(4*8)(R19), R3		// a4
   555  	MOVD	(5*8)(R19), R4		// a5
   556  	MOVD	(6*8)(R19), R5		// a6
   557  	MOVD	(7*8)(R19), R6		// a7
   558  	MOVD	(8*8)(R19), R7		// a8
   559  	MOVD	(9*8)(R19), R8		// a9
   560  	MOVD	(10*8)(R19), R9		// a10
   561  	MOVD	$0, R10			// vararg
   562  
   563  	CALL	R11
   564  
   565  	MOVD	R0, (11*8)(R19)		// r1
   566  	MOVD	R1, (12*8)(R19)		// r2
   567  
   568  	// Standard libc functions return -1 on error
   569  	// and set errno.
   570  	CMPW	$-1, R0
   571  	BNE	ok
   572  
   573  	// Get error code from libc.
   574  	CALL	libc_errno(SB)
   575  	MOVW	(R0), R0
   576  	MOVD	R0, (13*8)(R19)		// err
   577  
   578  ok:
   579  	RET
   580  
   581  // syscall10X calls a function in libc on behalf of the syscall package.
   582  // syscall10X takes a pointer to a struct like:
   583  // struct {
   584  //	fn    uintptr
   585  //	a1    uintptr
   586  //	a2    uintptr
   587  //	a3    uintptr
   588  //	a4    uintptr
   589  //	a5    uintptr
   590  //	a6    uintptr
   591  //	a7    uintptr
   592  //	a8    uintptr
   593  //	a9    uintptr
   594  //	a10   uintptr
   595  //	r1    uintptr
   596  //	r2    uintptr
   597  //	err   uintptr
   598  // }
   599  // syscall10X must be called on the g0 stack with the
   600  // C calling convention (use libcCall).
   601  //
   602  // syscall10X is like syscall10 but expects a 64-bit result
   603  // and tests for 64-bit -1 to decide there was an error.
   604  TEXT runtime·syscall10X(SB),NOSPLIT,$0
   605  	MOVD    R0, R19			// pointer to args
   606  
   607  	MOVD	(0*8)(R19), R11		// fn
   608  	MOVD	(1*8)(R19), R0		// a1
   609  	MOVD	(2*8)(R19), R1		// a2
   610  	MOVD	(3*8)(R19), R2		// a3
   611  	MOVD	(4*8)(R19), R3		// a4
   612  	MOVD	(5*8)(R19), R4		// a5
   613  	MOVD	(6*8)(R19), R5		// a6
   614  	MOVD	(7*8)(R19), R6		// a7
   615  	MOVD	(8*8)(R19), R7		// a8
   616  	MOVD	(9*8)(R19), R8		// a9
   617  	MOVD	(10*8)(R19), R9		// a10
   618  	MOVD	$0, R10			// vararg
   619  
   620  	CALL	R11
   621  
   622  	MOVD	R0, (11*8)(R19)		// r1
   623  	MOVD	R1, (12*8)(R19)		// r2
   624  
   625  	// Standard libc functions return -1 on error
   626  	// and set errno.
   627  	CMP	$-1, R0
   628  	BNE	ok
   629  
   630  	// Get error code from libc.
   631  	CALL	libc_errno(SB)
   632  	MOVW	(R0), R0
   633  	MOVD	R0, (13*8)(R19)		// err
   634  
   635  ok:
   636  	RET