Black Lives Matter. Support the Equal Justice Initiative.

Text file src/runtime/sys_darwin_arm64.s

Documentation: runtime

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

View as plain text