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

     1  // Copyright 2015 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, Darwin
     6  // System calls are implemented in libSystem, this file contains
     7  // trampolines that convert from Go to C calling convention.
     8  
     9  #include "go_asm.h"
    10  #include "go_tls.h"
    11  #include "textflag.h"
    12  #include "cgo/abi_arm64.h"
    13  
    14  #define CLOCK_REALTIME		0
    15  
    16  TEXT notok<>(SB),NOSPLIT,$0
    17  	MOVD	$0, R8
    18  	MOVD	R8, (R8)
    19  	B	0(PC)
    20  
    21  TEXT runtime·open_trampoline(SB),NOSPLIT,$0
    22  	SUB	$16, RSP
    23  	MOVW	8(R0), R1	// arg 2 flags
    24  	MOVW	12(R0), R2	// arg 3 mode
    25  	MOVW	R2, (RSP)	// arg 3 is variadic, pass on stack
    26  	MOVD	0(R0), R0	// arg 1 pathname
    27  	BL	libc_open(SB)
    28  	ADD	$16, RSP
    29  	RET
    30  
    31  TEXT runtime·close_trampoline(SB),NOSPLIT,$0
    32  	MOVW	0(R0), R0	// arg 1 fd
    33  	BL	libc_close(SB)
    34  	RET
    35  
    36  TEXT runtime·write_trampoline(SB),NOSPLIT,$0
    37  	MOVD	8(R0), R1	// arg 2 buf
    38  	MOVW	16(R0), R2	// arg 3 count
    39  	MOVW	0(R0), R0	// arg 1 fd
    40  	BL	libc_write(SB)
    41  	MOVD	$-1, R1
    42  	CMP	R0, R1
    43  	BNE	noerr
    44  	BL	libc_error(SB)
    45  	MOVW	(R0), R0
    46  	NEG	R0, R0		// caller expects negative errno value
    47  noerr:
    48  	RET
    49  
    50  TEXT runtime·read_trampoline(SB),NOSPLIT,$0
    51  	MOVD	8(R0), R1	// arg 2 buf
    52  	MOVW	16(R0), R2	// arg 3 count
    53  	MOVW	0(R0), R0	// arg 1 fd
    54  	BL	libc_read(SB)
    55  	MOVD	$-1, R1
    56  	CMP	R0, R1
    57  	BNE	noerr
    58  	BL	libc_error(SB)
    59  	MOVW	(R0), R0
    60  	NEG	R0, R0		// caller expects negative errno value
    61  noerr:
    62  	RET
    63  
    64  TEXT runtime·pipe_trampoline(SB),NOSPLIT,$0
    65  	BL	libc_pipe(SB)	// pointer already in R0
    66  	CMP	$0, R0
    67  	BEQ	3(PC)
    68  	BL	libc_error(SB)	// return negative errno value
    69  	NEG	R0, R0
    70  	RET
    71  
    72  TEXT runtime·exit_trampoline(SB),NOSPLIT|NOFRAME,$0
    73  	MOVW	0(R0), R0
    74  	BL	libc_exit(SB)
    75  	MOVD	$1234, R0
    76  	MOVD	$1002, R1
    77  	MOVD	R0, (R1)	// fail hard
    78  
    79  TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$0
    80  	MOVD	0(R0), R19	// signal
    81  	BL	libc_getpid(SB)
    82  	// arg 1 pid already in R0 from getpid
    83  	MOVD	R19, R1	// arg 2 signal
    84  	BL	libc_kill(SB)
    85  	RET
    86  
    87  TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
    88  	MOVD	R0, R19
    89  	MOVD	0(R19), R0	// arg 1 addr
    90  	MOVD	8(R19), R1	// arg 2 len
    91  	MOVW	16(R19), R2	// arg 3 prot
    92  	MOVW	20(R19), R3	// arg 4 flags
    93  	MOVW	24(R19), R4	// arg 5 fd
    94  	MOVW	28(R19), R5	// arg 6 off
    95  	BL	libc_mmap(SB)
    96  	MOVD	$0, R1
    97  	MOVD	$-1, R2
    98  	CMP	R0, R2
    99  	BNE	ok
   100  	BL	libc_error(SB)
   101  	MOVW	(R0), R1
   102  	MOVD	$0, R0
   103  ok:
   104  	MOVD	R0, 32(R19) // ret 1 p
   105  	MOVD	R1, 40(R19)	// ret 2 err
   106  	RET
   107  
   108  TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0
   109  	MOVD	8(R0), R1	// arg 2 len
   110  	MOVD	0(R0), R0	// arg 1 addr
   111  	BL	libc_munmap(SB)
   112  	CMP	$0, R0
   113  	BEQ	2(PC)
   114  	BL	notok<>(SB)
   115  	RET
   116  
   117  TEXT runtime·madvise_trampoline(SB),NOSPLIT,$0
   118  	MOVD	8(R0), R1	// arg 2 len
   119  	MOVW	16(R0), R2	// arg 3 advice
   120  	MOVD	0(R0), R0	// arg 1 addr
   121  	BL	libc_madvise(SB)
   122  	RET
   123  
   124  TEXT runtime·mlock_trampoline(SB),NOSPLIT,$0
   125  	MOVD	8(R0), R1	// arg 2 len
   126  	MOVD	0(R0), R0	// arg 1 addr
   127  	BL	libc_mlock(SB)
   128  	RET
   129  
   130  TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0
   131  	MOVD	8(R0), R1	// arg 2 new
   132  	MOVD	16(R0), R2	// arg 3 old
   133  	MOVW	0(R0), R0	// arg 1 which
   134  	BL	libc_setitimer(SB)
   135  	RET
   136  
   137  TEXT runtime·walltime_trampoline(SB),NOSPLIT,$0
   138  	MOVD	R0, R1			// arg 2 timespec
   139  	MOVW	$CLOCK_REALTIME, R0 	// arg 1 clock_id
   140  	BL	libc_clock_gettime(SB)
   141  	RET
   142  
   143  GLOBL timebase<>(SB),NOPTR,$(machTimebaseInfo__size)
   144  
   145  TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$40
   146  	MOVD	R0, R19
   147  	BL	libc_mach_absolute_time(SB)
   148  	MOVD	R0, 0(R19)
   149  	MOVW	timebase<>+machTimebaseInfo_numer(SB), R20
   150  	MOVD	$timebase<>+machTimebaseInfo_denom(SB), R21
   151  	LDARW	(R21), R21	// atomic read
   152  	CMP	$0, R21
   153  	BNE	initialized
   154  
   155  	SUB	$(machTimebaseInfo__size+15)/16*16, RSP
   156  	MOVD	RSP, R0
   157  	BL	libc_mach_timebase_info(SB)
   158  	MOVW	machTimebaseInfo_numer(RSP), R20
   159  	MOVW	machTimebaseInfo_denom(RSP), R21
   160  	ADD	$(machTimebaseInfo__size+15)/16*16, RSP
   161  
   162  	MOVW	R20, timebase<>+machTimebaseInfo_numer(SB)
   163  	MOVD	$timebase<>+machTimebaseInfo_denom(SB), R22
   164  	STLRW	R21, (R22)	// atomic write
   165  
   166  initialized:
   167  	MOVW	R20, 8(R19)
   168  	MOVW	R21, 12(R19)
   169  	RET
   170  
   171  TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
   172  	MOVW	sig+8(FP), R0
   173  	MOVD	info+16(FP), R1
   174  	MOVD	ctx+24(FP), R2
   175  	MOVD	fn+0(FP), R11
   176  	BL	(R11)
   177  	RET
   178  
   179  TEXT runtime·sigtramp(SB),NOSPLIT|TOPFRAME,$176
   180  	// Save callee-save registers in the case of signal forwarding.
   181  	// Please refer to https://golang.org/issue/31827 .
   182  	SAVE_R19_TO_R28(8*4)
   183  	SAVE_F8_TO_F15(8*14)
   184  
   185  	// Save arguments.
   186  	MOVW	R0, (8*1)(RSP)	// sig
   187  	MOVD	R1, (8*2)(RSP)	// info
   188  	MOVD	R2, (8*3)(RSP)	// ctx
   189  
   190  	// this might be called in external code context,
   191  	// where g is not set.
   192  	BL	runtime·load_g(SB)
   193  
   194  #ifdef GOOS_ios
   195  	MOVD	RSP, R6
   196  	CMP	$0, g
   197  	BEQ	nog
   198  	// iOS always use the main stack to run the signal handler.
   199  	// We need to switch to gsignal ourselves.
   200  	MOVD	g_m(g), R11
   201  	MOVD	m_gsignal(R11), R5
   202  	MOVD	(g_stack+stack_hi)(R5), R6
   203  
   204  nog:
   205  	// Restore arguments.
   206  	MOVW	(8*1)(RSP), R0
   207  	MOVD	(8*2)(RSP), R1
   208  	MOVD	(8*3)(RSP), R2
   209  
   210  	// Reserve space for args and the stack pointer on the
   211  	// gsignal stack.
   212  	SUB	$48, R6
   213  	// Save stack pointer.
   214  	MOVD	RSP, R4
   215  	MOVD	R4, (8*4)(R6)
   216  	// Switch to gsignal stack.
   217  	MOVD	R6, RSP
   218  
   219  	// Save arguments.
   220  	MOVW	R0, (8*1)(RSP)
   221  	MOVD	R1, (8*2)(RSP)
   222  	MOVD	R2, (8*3)(RSP)
   223  #endif
   224  
   225  	// Call sigtrampgo.
   226  	MOVD	$runtime·sigtrampgo(SB), R11
   227  	BL	(R11)
   228  
   229  #ifdef GOOS_ios
   230  	// Switch to old stack.
   231  	MOVD	(8*4)(RSP), R5
   232  	MOVD	R5, RSP
   233  #endif
   234  
   235  	// Restore callee-save registers.
   236  	RESTORE_R19_TO_R28(8*4)
   237  	RESTORE_F8_TO_F15(8*14)
   238  
   239  	RET
   240  
   241  TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
   242  	JMP	runtime·sigtramp(SB)
   243  
   244  TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$0
   245  	MOVD	8(R0), R1	// arg 2 new
   246  	MOVD	16(R0), R2	// arg 3 old
   247  	MOVW	0(R0), R0	// arg 1 how
   248  	BL	libc_pthread_sigmask(SB)
   249  	CMP	$0, R0
   250  	BEQ	2(PC)
   251  	BL	notok<>(SB)
   252  	RET
   253  
   254  TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$0
   255  	MOVD	8(R0), R1	// arg 2 new
   256  	MOVD	16(R0), R2	// arg 3 old
   257  	MOVW	0(R0), R0	// arg 1 how
   258  	BL	libc_sigaction(SB)
   259  	CMP	$0, R0
   260  	BEQ	2(PC)
   261  	BL	notok<>(SB)
   262  	RET
   263  
   264  TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0
   265  	MOVW	0(R0), R0	// arg 1 usec
   266  	BL	libc_usleep(SB)
   267  	RET
   268  
   269  TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0
   270  	MOVW	8(R0), R1	// arg 2 miblen
   271  	MOVD	16(R0), R2	// arg 3 oldp
   272  	MOVD	24(R0), R3	// arg 4 oldlenp
   273  	MOVD	32(R0), R4	// arg 5 newp
   274  	MOVD	40(R0), R5	// arg 6 newlen
   275  	MOVD	0(R0), R0	// arg 1 mib
   276  	BL	libc_sysctl(SB)
   277  	RET
   278  
   279  TEXT runtime·sysctlbyname_trampoline(SB),NOSPLIT,$0
   280  	MOVD	8(R0), R1	// arg 2 oldp
   281  	MOVD	16(R0), R2	// arg 3 oldlenp
   282  	MOVD	24(R0), R3	// arg 4 newp
   283  	MOVD	32(R0), R4	// arg 5 newlen
   284  	MOVD	0(R0), R0	// arg 1 name
   285  	BL	libc_sysctlbyname(SB)
   286  	RET
   287  
   288  
   289  TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0
   290  	BL	libc_kqueue(SB)
   291  	RET
   292  
   293  TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0
   294  	MOVD	8(R0), R1	// arg 2 keventt
   295  	MOVW	16(R0), R2	// arg 3 nch
   296  	MOVD	24(R0), R3	// arg 4 ev
   297  	MOVW	32(R0), R4	// arg 5 nev
   298  	MOVD	40(R0), R5	// arg 6 ts
   299  	MOVW	0(R0), R0	// arg 1 kq
   300  	BL	libc_kevent(SB)
   301  	MOVD	$-1, R2
   302  	CMP	R0, R2
   303  	BNE	ok
   304  	BL	libc_error(SB)
   305  	MOVW	(R0), R0	// errno
   306  	NEG	R0, R0	// caller wants it as a negative error code
   307  ok:
   308  	RET
   309  
   310  TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0
   311  	SUB	$16, RSP
   312  	MOVW	4(R0), R1	// arg 2 cmd
   313  	MOVW	8(R0), R2	// arg 3 arg
   314  	MOVW	R2, (RSP)	// arg 3 is variadic, pass on stack
   315  	MOVW	0(R0), R0	// arg 1 fd
   316  	BL	libc_fcntl(SB)
   317  	ADD	$16, RSP
   318  	RET
   319  
   320  TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
   321  #ifdef GOOS_ios
   322  	// sigaltstack on iOS is not supported and will always
   323  	// run the signal handler on the main stack, so our sigtramp has
   324  	// to do the stack switch ourselves.
   325  	MOVW	$43, R0
   326  	BL	libc_exit(SB)
   327  #else
   328  	MOVD	8(R0), R1		// arg 2 old
   329  	MOVD	0(R0), R0		// arg 1 new
   330  	CALL	libc_sigaltstack(SB)
   331  	CBZ	R0, 2(PC)
   332  	BL	notok<>(SB)
   333  #endif
   334  	RET
   335  
   336  // Thread related functions
   337  
   338  // mstart_stub is the first function executed on a new thread started by pthread_create.
   339  // It just does some low-level setup and then calls mstart.
   340  // Note: called with the C calling convention.
   341  TEXT runtime·mstart_stub(SB),NOSPLIT,$160
   342  	// R0 points to the m.
   343  	// We are already on m's g0 stack.
   344  
   345  	// Save callee-save registers.
   346  	SAVE_R19_TO_R28(8)
   347  	SAVE_F8_TO_F15(88)
   348  
   349  	MOVD	m_g0(R0), g
   350  	BL	·save_g(SB)
   351  
   352  	BL	runtime·mstart(SB)
   353  
   354  	// Restore callee-save registers.
   355  	RESTORE_R19_TO_R28(8)
   356  	RESTORE_F8_TO_F15(88)
   357  
   358  	// Go is all done with this OS thread.
   359  	// Tell pthread everything is ok (we never join with this thread, so
   360  	// the value here doesn't really matter).
   361  	MOVD	$0, R0
   362  
   363  	RET
   364  
   365  TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0
   366  	MOVD	0(R0), R0	// arg 1 attr
   367  	BL	libc_pthread_attr_init(SB)
   368  	RET
   369  
   370  TEXT runtime·pthread_attr_getstacksize_trampoline(SB),NOSPLIT,$0
   371  	MOVD	8(R0), R1	// arg 2 size
   372  	MOVD	0(R0), R0	// arg 1 attr
   373  	BL	libc_pthread_attr_getstacksize(SB)
   374  	RET
   375  
   376  TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0
   377  	MOVD	8(R0), R1	// arg 2 state
   378  	MOVD	0(R0), R0	// arg 1 attr
   379  	BL	libc_pthread_attr_setdetachstate(SB)
   380  	RET
   381  
   382  TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0
   383  	SUB	$16, RSP
   384  	MOVD	0(R0), R1	// arg 2 state
   385  	MOVD	8(R0), R2	// arg 3 start
   386  	MOVD	16(R0), R3	// arg 4 arg
   387  	MOVD	RSP, R0 	// arg 1 &threadid (which we throw away)
   388  	BL	libc_pthread_create(SB)
   389  	ADD	$16, RSP
   390  	RET
   391  
   392  TEXT runtime·raise_trampoline(SB),NOSPLIT,$0
   393  	MOVW	0(R0), R0	// arg 1 sig
   394  	BL	libc_raise(SB)
   395  	RET
   396  
   397  TEXT runtime·pthread_mutex_init_trampoline(SB),NOSPLIT,$0
   398  	MOVD	8(R0), R1	// arg 2 attr
   399  	MOVD	0(R0), R0	// arg 1 mutex
   400  	BL	libc_pthread_mutex_init(SB)
   401  	RET
   402  
   403  TEXT runtime·pthread_mutex_lock_trampoline(SB),NOSPLIT,$0
   404  	MOVD	0(R0), R0	// arg 1 mutex
   405  	BL	libc_pthread_mutex_lock(SB)
   406  	RET
   407  
   408  TEXT runtime·pthread_mutex_unlock_trampoline(SB),NOSPLIT,$0
   409  	MOVD	0(R0), R0	// arg 1 mutex
   410  	BL	libc_pthread_mutex_unlock(SB)
   411  	RET
   412  
   413  TEXT runtime·pthread_cond_init_trampoline(SB),NOSPLIT,$0
   414  	MOVD	8(R0), R1	// arg 2 attr
   415  	MOVD	0(R0), R0	// arg 1 cond
   416  	BL	libc_pthread_cond_init(SB)
   417  	RET
   418  
   419  TEXT runtime·pthread_cond_wait_trampoline(SB),NOSPLIT,$0
   420  	MOVD	8(R0), R1	// arg 2 mutex
   421  	MOVD	0(R0), R0	// arg 1 cond
   422  	BL	libc_pthread_cond_wait(SB)
   423  	RET
   424  
   425  TEXT runtime·pthread_cond_timedwait_relative_np_trampoline(SB),NOSPLIT,$0
   426  	MOVD	8(R0), R1	// arg 2 mutex
   427  	MOVD	16(R0), R2	// arg 3 timeout
   428  	MOVD	0(R0), R0	// arg 1 cond
   429  	BL	libc_pthread_cond_timedwait_relative_np(SB)
   430  	RET
   431  
   432  TEXT runtime·pthread_cond_signal_trampoline(SB),NOSPLIT,$0
   433  	MOVD	0(R0), R0	// arg 1 cond
   434  	BL	libc_pthread_cond_signal(SB)
   435  	RET
   436  
   437  TEXT runtime·pthread_self_trampoline(SB),NOSPLIT,$0
   438  	MOVD	R0, R19		// R19 is callee-save
   439  	BL	libc_pthread_self(SB)
   440  	MOVD	R0, 0(R19)	// return value
   441  	RET
   442  
   443  TEXT runtime·pthread_kill_trampoline(SB),NOSPLIT,$0
   444  	MOVD	8(R0), R1	// arg 2 sig
   445  	MOVD	0(R0), R0	// arg 1 thread
   446  	BL	libc_pthread_kill(SB)
   447  	RET
   448  
   449  TEXT runtime·pthread_key_create_trampoline(SB),NOSPLIT,$0
   450  	MOVD	8(R0), R1	// arg 2 destructor
   451  	MOVD	0(R0), R0	// arg 1 *key
   452  	BL	libc_pthread_key_create(SB)
   453  	RET
   454  
   455  TEXT runtime·pthread_setspecific_trampoline(SB),NOSPLIT,$0
   456  	MOVD	8(R0), R1	// arg 2 value
   457  	MOVD	0(R0), R0	// arg 1 key
   458  	BL	libc_pthread_setspecific(SB)
   459  	RET
   460  
   461  TEXT runtime·osinit_hack_trampoline(SB),NOSPLIT,$0
   462  	MOVD	$0, R0	// arg 1 val
   463  	BL	libc_notify_is_valid_token(SB)
   464  	BL	libc_xpc_date_create_from_current(SB)
   465  	RET
   466  
   467  // syscall calls a function in libc on behalf of the syscall package.
   468  // syscall takes a pointer to a struct like:
   469  // struct {
   470  //	fn    uintptr
   471  //	a1    uintptr
   472  //	a2    uintptr
   473  //	a3    uintptr
   474  //	r1    uintptr
   475  //	r2    uintptr
   476  //	err   uintptr
   477  // }
   478  // syscall must be called on the g0 stack with the
   479  // C calling convention (use libcCall).
   480  TEXT runtime·syscall(SB),NOSPLIT,$0
   481  	SUB	$16, RSP	// push structure pointer
   482  	MOVD	R0, 8(RSP)
   483  
   484  	MOVD	0(R0), R12	// fn
   485  	MOVD	16(R0), R1	// a2
   486  	MOVD	24(R0), R2	// a3
   487  	MOVD	8(R0), R0	// a1
   488  
   489  	// If fn is declared as vararg, we have to pass the vararg arguments on the stack.
   490  	// (Because ios decided not to adhere to the standard arm64 calling convention, sigh...)
   491  	// The only libSystem calls we support that are vararg are open, fcntl, and ioctl,
   492  	// which are all of the form fn(x, y, ...). So we just need to put the 3rd arg
   493  	// on the stack as well.
   494  	// If we ever have other vararg libSystem calls, we might need to handle more cases.
   495  	MOVD	R2, (RSP)
   496  
   497  	BL	(R12)
   498  
   499  	MOVD	8(RSP), R2	// pop structure pointer
   500  	ADD	$16, RSP
   501  	MOVD	R0, 32(R2)	// save r1
   502  	MOVD	R1, 40(R2)	// save r2
   503  	CMPW	$-1, R0
   504  	BNE	ok
   505  	SUB	$16, RSP	// push structure pointer
   506  	MOVD	R2, 8(RSP)
   507  	BL	libc_error(SB)
   508  	MOVW	(R0), R0
   509  	MOVD	8(RSP), R2	// pop structure pointer
   510  	ADD	$16, RSP
   511  	MOVD	R0, 48(R2)	// save err
   512  ok:
   513  	RET
   514  
   515  // syscallX calls a function in libc on behalf of the syscall package.
   516  // syscallX takes a pointer to a struct like:
   517  // struct {
   518  //	fn    uintptr
   519  //	a1    uintptr
   520  //	a2    uintptr
   521  //	a3    uintptr
   522  //	r1    uintptr
   523  //	r2    uintptr
   524  //	err   uintptr
   525  // }
   526  // syscallX must be called on the g0 stack with the
   527  // C calling convention (use libcCall).
   528  TEXT runtime·syscallX(SB),NOSPLIT,$0
   529  	SUB	$16, RSP	// push structure pointer
   530  	MOVD	R0, (RSP)
   531  
   532  	MOVD	0(R0), R12	// fn
   533  	MOVD	16(R0), R1	// a2
   534  	MOVD	24(R0), R2	// a3
   535  	MOVD	8(R0), R0	// a1
   536  	BL	(R12)
   537  
   538  	MOVD	(RSP), R2	// pop structure pointer
   539  	ADD	$16, RSP
   540  	MOVD	R0, 32(R2)	// save r1
   541  	MOVD	R1, 40(R2)	// save r2
   542  	CMP	$-1, R0
   543  	BNE	ok
   544  	SUB	$16, RSP	// push structure pointer
   545  	MOVD	R2, (RSP)
   546  	BL	libc_error(SB)
   547  	MOVW	(R0), R0
   548  	MOVD	(RSP), R2	// pop structure pointer
   549  	ADD	$16, RSP
   550  	MOVD	R0, 48(R2)	// save err
   551  ok:
   552  	RET
   553  
   554  // syscallPtr is like syscallX except that the libc function reports an
   555  // error by returning NULL and setting errno.
   556  TEXT runtime·syscallPtr(SB),NOSPLIT,$0
   557  	SUB	$16, RSP	// push structure pointer
   558  	MOVD	R0, (RSP)
   559  
   560  	MOVD	0(R0), R12	// fn
   561  	MOVD	16(R0), R1	// a2
   562  	MOVD	24(R0), R2	// a3
   563  	MOVD	8(R0), R0	// a1
   564  	BL	(R12)
   565  
   566  	MOVD	(RSP), R2	// pop structure pointer
   567  	ADD	$16, RSP
   568  	MOVD	R0, 32(R2)	// save r1
   569  	MOVD	R1, 40(R2)	// save r2
   570  	CMP	$0, R0
   571  	BNE	ok
   572  	SUB	$16, RSP	// push structure pointer
   573  	MOVD	R2, (RSP)
   574  	BL	libc_error(SB)
   575  	MOVW	(R0), R0
   576  	MOVD	(RSP), R2	// pop structure pointer
   577  	ADD	$16, RSP
   578  	MOVD	R0, 48(R2)	// save err
   579  ok:
   580  	RET
   581  
   582  // syscall6 calls a function in libc on behalf of the syscall package.
   583  // syscall6 takes a pointer to a struct like:
   584  // struct {
   585  //	fn    uintptr
   586  //	a1    uintptr
   587  //	a2    uintptr
   588  //	a3    uintptr
   589  //	a4    uintptr
   590  //	a5    uintptr
   591  //	a6    uintptr
   592  //	r1    uintptr
   593  //	r2    uintptr
   594  //	err   uintptr
   595  // }
   596  // syscall6 must be called on the g0 stack with the
   597  // C calling convention (use libcCall).
   598  TEXT runtime·syscall6(SB),NOSPLIT,$0
   599  	SUB	$16, RSP	// push structure pointer
   600  	MOVD	R0, 8(RSP)
   601  
   602  	MOVD	0(R0), R12	// fn
   603  	MOVD	16(R0), R1	// a2
   604  	MOVD	24(R0), R2	// a3
   605  	MOVD	32(R0), R3	// a4
   606  	MOVD	40(R0), R4	// a5
   607  	MOVD	48(R0), R5	// a6
   608  	MOVD	8(R0), R0	// a1
   609  
   610  	// If fn is declared as vararg, we have to pass the vararg arguments on the stack.
   611  	// See syscall above. The only function this applies to is openat, for which the 4th
   612  	// arg must be on the stack.
   613  	MOVD	R3, (RSP)
   614  
   615  	BL	(R12)
   616  
   617  	MOVD	8(RSP), R2	// pop structure pointer
   618  	ADD	$16, RSP
   619  	MOVD	R0, 56(R2)	// save r1
   620  	MOVD	R1, 64(R2)	// save r2
   621  	CMPW	$-1, R0
   622  	BNE	ok
   623  	SUB	$16, RSP	// push structure pointer
   624  	MOVD	R2, 8(RSP)
   625  	BL	libc_error(SB)
   626  	MOVW	(R0), R0
   627  	MOVD	8(RSP), R2	// pop structure pointer
   628  	ADD	$16, RSP
   629  	MOVD	R0, 72(R2)	// save err
   630  ok:
   631  	RET
   632  
   633  // syscall6X calls a function in libc on behalf of the syscall package.
   634  // syscall6X takes a pointer to a struct like:
   635  // struct {
   636  //	fn    uintptr
   637  //	a1    uintptr
   638  //	a2    uintptr
   639  //	a3    uintptr
   640  //	a4    uintptr
   641  //	a5    uintptr
   642  //	a6    uintptr
   643  //	r1    uintptr
   644  //	r2    uintptr
   645  //	err   uintptr
   646  // }
   647  // syscall6X must be called on the g0 stack with the
   648  // C calling convention (use libcCall).
   649  TEXT runtime·syscall6X(SB),NOSPLIT,$0
   650  	SUB	$16, RSP	// push structure pointer
   651  	MOVD	R0, (RSP)
   652  
   653  	MOVD	0(R0), R12	// fn
   654  	MOVD	16(R0), R1	// a2
   655  	MOVD	24(R0), R2	// a3
   656  	MOVD	32(R0), R3	// a4
   657  	MOVD	40(R0), R4	// a5
   658  	MOVD	48(R0), R5	// a6
   659  	MOVD	8(R0), R0	// a1
   660  	BL	(R12)
   661  
   662  	MOVD	(RSP), R2	// pop structure pointer
   663  	ADD	$16, RSP
   664  	MOVD	R0, 56(R2)	// save r1
   665  	MOVD	R1, 64(R2)	// save r2
   666  	CMP	$-1, R0
   667  	BNE	ok
   668  	SUB	$16, RSP	// push structure pointer
   669  	MOVD	R2, (RSP)
   670  	BL	libc_error(SB)
   671  	MOVW	(R0), R0
   672  	MOVD	(RSP), R2	// pop structure pointer
   673  	ADD	$16, RSP
   674  	MOVD	R0, 72(R2)	// save err
   675  ok:
   676  	RET
   677  
   678  // syscall9 calls a function in libc on behalf of the syscall package.
   679  // syscall9 takes a pointer to a struct like:
   680  // struct {
   681  //	fn    uintptr
   682  //	a1    uintptr
   683  //	a2    uintptr
   684  //	a3    uintptr
   685  //	a4    uintptr
   686  //	a5    uintptr
   687  //	a6    uintptr
   688  //	a7    uintptr
   689  //	a8    uintptr
   690  //	a9    uintptr
   691  //	r1    uintptr
   692  //	r2    uintptr
   693  //	err   uintptr
   694  // }
   695  // syscall9 must be called on the g0 stack with the
   696  // C calling convention (use libcCall).
   697  TEXT runtime·syscall9(SB),NOSPLIT,$0
   698  	SUB	$16, RSP	// push structure pointer
   699  	MOVD	R0, 8(RSP)
   700  
   701  	MOVD	0(R0), R12	// fn
   702  	MOVD	16(R0), R1	// a2
   703  	MOVD	24(R0), R2	// a3
   704  	MOVD	32(R0), R3	// a4
   705  	MOVD	40(R0), R4	// a5
   706  	MOVD	48(R0), R5	// a6
   707  	MOVD	56(R0), R6	// a7
   708  	MOVD	64(R0), R7	// a8
   709  	MOVD	72(R0), R8	// a9
   710  	MOVD	8(R0), R0	// a1
   711  
   712  	// If fn is declared as vararg, we have to pass the vararg arguments on the stack.
   713  	// See syscall above. The only function this applies to is openat, for which the 4th
   714  	// arg must be on the stack.
   715  	MOVD	R3, (RSP)
   716  
   717  	BL	(R12)
   718  
   719  	MOVD	8(RSP), R2	// pop structure pointer
   720  	ADD	$16, RSP
   721  	MOVD	R0, 80(R2)	// save r1
   722  	MOVD	R1, 88(R2)	// save r2
   723  	CMPW	$-1, R0
   724  	BNE	ok
   725  	SUB	$16, RSP	// push structure pointer
   726  	MOVD	R2, 8(RSP)
   727  	BL	libc_error(SB)
   728  	MOVW	(R0), R0
   729  	MOVD	8(RSP), R2	// pop structure pointer
   730  	ADD	$16, RSP
   731  	MOVD	R0, 96(R2)	// save err
   732  ok:
   733  	RET
   734  
   735  // syscall_x509 is for crypto/x509. It is like syscall6 but does not check for errors,
   736  // takes 5 uintptrs and 1 float64, and only returns one value,
   737  // for use with standard C ABI functions.
   738  TEXT runtime·syscall_x509(SB),NOSPLIT,$0
   739  	SUB	$16, RSP	// push structure pointer
   740  	MOVD	R0, (RSP)
   741  
   742  	MOVD	0(R0), R12	// fn
   743  	MOVD	16(R0), R1	// a2
   744  	MOVD	24(R0), R2	// a3
   745  	MOVD	32(R0), R3	// a4
   746  	MOVD	40(R0), R4	// a5
   747  	FMOVD	48(R0), F0	// f1
   748  	MOVD	8(R0), R0	// a1
   749  	BL	(R12)
   750  
   751  	MOVD	(RSP), R2	// pop structure pointer
   752  	ADD	$16, RSP
   753  	MOVD	R0, 56(R2)	// save r1
   754  	RET