github.com/lovishpuri/go-40569/src@v0.0.0-20230519171745-f8623e7c56cf/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  	MOVD	$-1, R1
   318  	CMP	R0, R1
   319  	BNE	noerr
   320  	BL	libc_error(SB)
   321  	MOVW	(R0), R0
   322  	NEG	R0, R0		// caller expects negative errno value
   323  noerr:
   324  	ADD	$16, RSP
   325  	RET
   326  
   327  TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
   328  #ifdef GOOS_ios
   329  	// sigaltstack on iOS is not supported and will always
   330  	// run the signal handler on the main stack, so our sigtramp has
   331  	// to do the stack switch ourselves.
   332  	MOVW	$43, R0
   333  	BL	libc_exit(SB)
   334  #else
   335  	MOVD	8(R0), R1		// arg 2 old
   336  	MOVD	0(R0), R0		// arg 1 new
   337  	CALL	libc_sigaltstack(SB)
   338  	CBZ	R0, 2(PC)
   339  	BL	notok<>(SB)
   340  #endif
   341  	RET
   342  
   343  // Thread related functions
   344  
   345  // mstart_stub is the first function executed on a new thread started by pthread_create.
   346  // It just does some low-level setup and then calls mstart.
   347  // Note: called with the C calling convention.
   348  TEXT runtime·mstart_stub(SB),NOSPLIT,$160
   349  	// R0 points to the m.
   350  	// We are already on m's g0 stack.
   351  
   352  	// Save callee-save registers.
   353  	SAVE_R19_TO_R28(8)
   354  	SAVE_F8_TO_F15(88)
   355  
   356  	MOVD	m_g0(R0), g
   357  	BL	·save_g(SB)
   358  
   359  	BL	runtime·mstart(SB)
   360  
   361  	// Restore callee-save registers.
   362  	RESTORE_R19_TO_R28(8)
   363  	RESTORE_F8_TO_F15(88)
   364  
   365  	// Go is all done with this OS thread.
   366  	// Tell pthread everything is ok (we never join with this thread, so
   367  	// the value here doesn't really matter).
   368  	MOVD	$0, R0
   369  
   370  	RET
   371  
   372  TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0
   373  	MOVD	0(R0), R0	// arg 1 attr
   374  	BL	libc_pthread_attr_init(SB)
   375  	RET
   376  
   377  TEXT runtime·pthread_attr_getstacksize_trampoline(SB),NOSPLIT,$0
   378  	MOVD	8(R0), R1	// arg 2 size
   379  	MOVD	0(R0), R0	// arg 1 attr
   380  	BL	libc_pthread_attr_getstacksize(SB)
   381  	RET
   382  
   383  TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0
   384  	MOVD	8(R0), R1	// arg 2 state
   385  	MOVD	0(R0), R0	// arg 1 attr
   386  	BL	libc_pthread_attr_setdetachstate(SB)
   387  	RET
   388  
   389  TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0
   390  	SUB	$16, RSP
   391  	MOVD	0(R0), R1	// arg 2 state
   392  	MOVD	8(R0), R2	// arg 3 start
   393  	MOVD	16(R0), R3	// arg 4 arg
   394  	MOVD	RSP, R0 	// arg 1 &threadid (which we throw away)
   395  	BL	libc_pthread_create(SB)
   396  	ADD	$16, RSP
   397  	RET
   398  
   399  TEXT runtime·raise_trampoline(SB),NOSPLIT,$0
   400  	MOVW	0(R0), R0	// arg 1 sig
   401  	BL	libc_raise(SB)
   402  	RET
   403  
   404  TEXT runtime·pthread_mutex_init_trampoline(SB),NOSPLIT,$0
   405  	MOVD	8(R0), R1	// arg 2 attr
   406  	MOVD	0(R0), R0	// arg 1 mutex
   407  	BL	libc_pthread_mutex_init(SB)
   408  	RET
   409  
   410  TEXT runtime·pthread_mutex_lock_trampoline(SB),NOSPLIT,$0
   411  	MOVD	0(R0), R0	// arg 1 mutex
   412  	BL	libc_pthread_mutex_lock(SB)
   413  	RET
   414  
   415  TEXT runtime·pthread_mutex_unlock_trampoline(SB),NOSPLIT,$0
   416  	MOVD	0(R0), R0	// arg 1 mutex
   417  	BL	libc_pthread_mutex_unlock(SB)
   418  	RET
   419  
   420  TEXT runtime·pthread_cond_init_trampoline(SB),NOSPLIT,$0
   421  	MOVD	8(R0), R1	// arg 2 attr
   422  	MOVD	0(R0), R0	// arg 1 cond
   423  	BL	libc_pthread_cond_init(SB)
   424  	RET
   425  
   426  TEXT runtime·pthread_cond_wait_trampoline(SB),NOSPLIT,$0
   427  	MOVD	8(R0), R1	// arg 2 mutex
   428  	MOVD	0(R0), R0	// arg 1 cond
   429  	BL	libc_pthread_cond_wait(SB)
   430  	RET
   431  
   432  TEXT runtime·pthread_cond_timedwait_relative_np_trampoline(SB),NOSPLIT,$0
   433  	MOVD	8(R0), R1	// arg 2 mutex
   434  	MOVD	16(R0), R2	// arg 3 timeout
   435  	MOVD	0(R0), R0	// arg 1 cond
   436  	BL	libc_pthread_cond_timedwait_relative_np(SB)
   437  	RET
   438  
   439  TEXT runtime·pthread_cond_signal_trampoline(SB),NOSPLIT,$0
   440  	MOVD	0(R0), R0	// arg 1 cond
   441  	BL	libc_pthread_cond_signal(SB)
   442  	RET
   443  
   444  TEXT runtime·pthread_self_trampoline(SB),NOSPLIT,$0
   445  	MOVD	R0, R19		// R19 is callee-save
   446  	BL	libc_pthread_self(SB)
   447  	MOVD	R0, 0(R19)	// return value
   448  	RET
   449  
   450  TEXT runtime·pthread_kill_trampoline(SB),NOSPLIT,$0
   451  	MOVD	8(R0), R1	// arg 2 sig
   452  	MOVD	0(R0), R0	// arg 1 thread
   453  	BL	libc_pthread_kill(SB)
   454  	RET
   455  
   456  TEXT runtime·pthread_key_create_trampoline(SB),NOSPLIT,$0
   457  	MOVD	8(R0), R1	// arg 2 destructor
   458  	MOVD	0(R0), R0	// arg 1 *key
   459  	BL	libc_pthread_key_create(SB)
   460  	RET
   461  
   462  TEXT runtime·pthread_setspecific_trampoline(SB),NOSPLIT,$0
   463  	MOVD	8(R0), R1	// arg 2 value
   464  	MOVD	0(R0), R0	// arg 1 key
   465  	BL	libc_pthread_setspecific(SB)
   466  	RET
   467  
   468  TEXT runtime·osinit_hack_trampoline(SB),NOSPLIT,$0
   469  	MOVD	$0, R0	// arg 1 val
   470  	BL	libc_notify_is_valid_token(SB)
   471  	BL	libc_xpc_date_create_from_current(SB)
   472  	RET
   473  
   474  // syscall calls a function in libc on behalf of the syscall package.
   475  // syscall takes a pointer to a struct like:
   476  // struct {
   477  //	fn    uintptr
   478  //	a1    uintptr
   479  //	a2    uintptr
   480  //	a3    uintptr
   481  //	r1    uintptr
   482  //	r2    uintptr
   483  //	err   uintptr
   484  // }
   485  // syscall must be called on the g0 stack with the
   486  // C calling convention (use libcCall).
   487  TEXT runtime·syscall(SB),NOSPLIT,$0
   488  	SUB	$16, RSP	// push structure pointer
   489  	MOVD	R0, 8(RSP)
   490  
   491  	MOVD	0(R0), R12	// fn
   492  	MOVD	16(R0), R1	// a2
   493  	MOVD	24(R0), R2	// a3
   494  	MOVD	8(R0), R0	// a1
   495  
   496  	// If fn is declared as vararg, we have to pass the vararg arguments on the stack.
   497  	// (Because ios decided not to adhere to the standard arm64 calling convention, sigh...)
   498  	// The only libSystem calls we support that are vararg are open, fcntl, and ioctl,
   499  	// which are all of the form fn(x, y, ...). So we just need to put the 3rd arg
   500  	// on the stack as well.
   501  	// If we ever have other vararg libSystem calls, we might need to handle more cases.
   502  	MOVD	R2, (RSP)
   503  
   504  	BL	(R12)
   505  
   506  	MOVD	8(RSP), R2	// pop structure pointer
   507  	ADD	$16, RSP
   508  	MOVD	R0, 32(R2)	// save r1
   509  	MOVD	R1, 40(R2)	// save r2
   510  	CMPW	$-1, R0
   511  	BNE	ok
   512  	SUB	$16, RSP	// push structure pointer
   513  	MOVD	R2, 8(RSP)
   514  	BL	libc_error(SB)
   515  	MOVW	(R0), R0
   516  	MOVD	8(RSP), R2	// pop structure pointer
   517  	ADD	$16, RSP
   518  	MOVD	R0, 48(R2)	// save err
   519  ok:
   520  	RET
   521  
   522  // syscallX calls a function in libc on behalf of the syscall package.
   523  // syscallX takes a pointer to a struct like:
   524  // struct {
   525  //	fn    uintptr
   526  //	a1    uintptr
   527  //	a2    uintptr
   528  //	a3    uintptr
   529  //	r1    uintptr
   530  //	r2    uintptr
   531  //	err   uintptr
   532  // }
   533  // syscallX must be called on the g0 stack with the
   534  // C calling convention (use libcCall).
   535  TEXT runtime·syscallX(SB),NOSPLIT,$0
   536  	SUB	$16, RSP	// push structure pointer
   537  	MOVD	R0, (RSP)
   538  
   539  	MOVD	0(R0), R12	// fn
   540  	MOVD	16(R0), R1	// a2
   541  	MOVD	24(R0), R2	// a3
   542  	MOVD	8(R0), R0	// a1
   543  	BL	(R12)
   544  
   545  	MOVD	(RSP), R2	// pop structure pointer
   546  	ADD	$16, RSP
   547  	MOVD	R0, 32(R2)	// save r1
   548  	MOVD	R1, 40(R2)	// save r2
   549  	CMP	$-1, R0
   550  	BNE	ok
   551  	SUB	$16, RSP	// push structure pointer
   552  	MOVD	R2, (RSP)
   553  	BL	libc_error(SB)
   554  	MOVW	(R0), R0
   555  	MOVD	(RSP), R2	// pop structure pointer
   556  	ADD	$16, RSP
   557  	MOVD	R0, 48(R2)	// save err
   558  ok:
   559  	RET
   560  
   561  // syscallPtr is like syscallX except that the libc function reports an
   562  // error by returning NULL and setting errno.
   563  TEXT runtime·syscallPtr(SB),NOSPLIT,$0
   564  	SUB	$16, RSP	// push structure pointer
   565  	MOVD	R0, (RSP)
   566  
   567  	MOVD	0(R0), R12	// fn
   568  	MOVD	16(R0), R1	// a2
   569  	MOVD	24(R0), R2	// a3
   570  	MOVD	8(R0), R0	// a1
   571  	BL	(R12)
   572  
   573  	MOVD	(RSP), R2	// pop structure pointer
   574  	ADD	$16, RSP
   575  	MOVD	R0, 32(R2)	// save r1
   576  	MOVD	R1, 40(R2)	// save r2
   577  	CMP	$0, R0
   578  	BNE	ok
   579  	SUB	$16, RSP	// push structure pointer
   580  	MOVD	R2, (RSP)
   581  	BL	libc_error(SB)
   582  	MOVW	(R0), R0
   583  	MOVD	(RSP), R2	// pop structure pointer
   584  	ADD	$16, RSP
   585  	MOVD	R0, 48(R2)	// save err
   586  ok:
   587  	RET
   588  
   589  // syscall6 calls a function in libc on behalf of the syscall package.
   590  // syscall6 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  //	r1    uintptr
   600  //	r2    uintptr
   601  //	err   uintptr
   602  // }
   603  // syscall6 must be called on the g0 stack with the
   604  // C calling convention (use libcCall).
   605  TEXT runtime·syscall6(SB),NOSPLIT,$0
   606  	SUB	$16, RSP	// push structure pointer
   607  	MOVD	R0, 8(RSP)
   608  
   609  	MOVD	0(R0), R12	// fn
   610  	MOVD	16(R0), R1	// a2
   611  	MOVD	24(R0), R2	// a3
   612  	MOVD	32(R0), R3	// a4
   613  	MOVD	40(R0), R4	// a5
   614  	MOVD	48(R0), R5	// a6
   615  	MOVD	8(R0), R0	// a1
   616  
   617  	// If fn is declared as vararg, we have to pass the vararg arguments on the stack.
   618  	// See syscall above. The only function this applies to is openat, for which the 4th
   619  	// arg must be on the stack.
   620  	MOVD	R3, (RSP)
   621  
   622  	BL	(R12)
   623  
   624  	MOVD	8(RSP), R2	// pop structure pointer
   625  	ADD	$16, RSP
   626  	MOVD	R0, 56(R2)	// save r1
   627  	MOVD	R1, 64(R2)	// save r2
   628  	CMPW	$-1, R0
   629  	BNE	ok
   630  	SUB	$16, RSP	// push structure pointer
   631  	MOVD	R2, 8(RSP)
   632  	BL	libc_error(SB)
   633  	MOVW	(R0), R0
   634  	MOVD	8(RSP), R2	// pop structure pointer
   635  	ADD	$16, RSP
   636  	MOVD	R0, 72(R2)	// save err
   637  ok:
   638  	RET
   639  
   640  // syscall6X calls a function in libc on behalf of the syscall package.
   641  // syscall6X takes a pointer to a struct like:
   642  // struct {
   643  //	fn    uintptr
   644  //	a1    uintptr
   645  //	a2    uintptr
   646  //	a3    uintptr
   647  //	a4    uintptr
   648  //	a5    uintptr
   649  //	a6    uintptr
   650  //	r1    uintptr
   651  //	r2    uintptr
   652  //	err   uintptr
   653  // }
   654  // syscall6X must be called on the g0 stack with the
   655  // C calling convention (use libcCall).
   656  TEXT runtime·syscall6X(SB),NOSPLIT,$0
   657  	SUB	$16, RSP	// push structure pointer
   658  	MOVD	R0, (RSP)
   659  
   660  	MOVD	0(R0), R12	// fn
   661  	MOVD	16(R0), R1	// a2
   662  	MOVD	24(R0), R2	// a3
   663  	MOVD	32(R0), R3	// a4
   664  	MOVD	40(R0), R4	// a5
   665  	MOVD	48(R0), R5	// a6
   666  	MOVD	8(R0), R0	// a1
   667  	BL	(R12)
   668  
   669  	MOVD	(RSP), R2	// pop structure pointer
   670  	ADD	$16, RSP
   671  	MOVD	R0, 56(R2)	// save r1
   672  	MOVD	R1, 64(R2)	// save r2
   673  	CMP	$-1, R0
   674  	BNE	ok
   675  	SUB	$16, RSP	// push structure pointer
   676  	MOVD	R2, (RSP)
   677  	BL	libc_error(SB)
   678  	MOVW	(R0), R0
   679  	MOVD	(RSP), R2	// pop structure pointer
   680  	ADD	$16, RSP
   681  	MOVD	R0, 72(R2)	// save err
   682  ok:
   683  	RET
   684  
   685  // syscall9 calls a function in libc on behalf of the syscall package.
   686  // syscall9 takes a pointer to a struct like:
   687  // struct {
   688  //	fn    uintptr
   689  //	a1    uintptr
   690  //	a2    uintptr
   691  //	a3    uintptr
   692  //	a4    uintptr
   693  //	a5    uintptr
   694  //	a6    uintptr
   695  //	a7    uintptr
   696  //	a8    uintptr
   697  //	a9    uintptr
   698  //	r1    uintptr
   699  //	r2    uintptr
   700  //	err   uintptr
   701  // }
   702  // syscall9 must be called on the g0 stack with the
   703  // C calling convention (use libcCall).
   704  TEXT runtime·syscall9(SB),NOSPLIT,$0
   705  	SUB	$16, RSP	// push structure pointer
   706  	MOVD	R0, 8(RSP)
   707  
   708  	MOVD	0(R0), R12	// fn
   709  	MOVD	16(R0), R1	// a2
   710  	MOVD	24(R0), R2	// a3
   711  	MOVD	32(R0), R3	// a4
   712  	MOVD	40(R0), R4	// a5
   713  	MOVD	48(R0), R5	// a6
   714  	MOVD	56(R0), R6	// a7
   715  	MOVD	64(R0), R7	// a8
   716  	MOVD	72(R0), R8	// a9
   717  	MOVD	8(R0), R0	// a1
   718  
   719  	// If fn is declared as vararg, we have to pass the vararg arguments on the stack.
   720  	// See syscall above. The only function this applies to is openat, for which the 4th
   721  	// arg must be on the stack.
   722  	MOVD	R3, (RSP)
   723  
   724  	BL	(R12)
   725  
   726  	MOVD	8(RSP), R2	// pop structure pointer
   727  	ADD	$16, RSP
   728  	MOVD	R0, 80(R2)	// save r1
   729  	MOVD	R1, 88(R2)	// save r2
   730  	CMPW	$-1, R0
   731  	BNE	ok
   732  	SUB	$16, RSP	// push structure pointer
   733  	MOVD	R2, 8(RSP)
   734  	BL	libc_error(SB)
   735  	MOVW	(R0), R0
   736  	MOVD	8(RSP), R2	// pop structure pointer
   737  	ADD	$16, RSP
   738  	MOVD	R0, 96(R2)	// save err
   739  ok:
   740  	RET
   741  
   742  // syscall_x509 is for crypto/x509. It is like syscall6 but does not check for errors,
   743  // takes 5 uintptrs and 1 float64, and only returns one value,
   744  // for use with standard C ABI functions.
   745  TEXT runtime·syscall_x509(SB),NOSPLIT,$0
   746  	SUB	$16, RSP	// push structure pointer
   747  	MOVD	R0, (RSP)
   748  
   749  	MOVD	0(R0), R12	// fn
   750  	MOVD	16(R0), R1	// a2
   751  	MOVD	24(R0), R2	// a3
   752  	MOVD	32(R0), R3	// a4
   753  	MOVD	40(R0), R4	// a5
   754  	FMOVD	48(R0), F0	// f1
   755  	MOVD	8(R0), R0	// a1
   756  	BL	(R12)
   757  
   758  	MOVD	(RSP), R2	// pop structure pointer
   759  	ADD	$16, RSP
   760  	MOVD	R0, 56(R2)	// save r1
   761  	RET