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