github.com/x04/go/src@v0.0.0-20200202162449-3d481ceb3525/runtime/sys_darwin_arm.s (about)

     1  // Copyright 2014 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 ARM, 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  	MOVW	$0, R8
    15  	MOVW	R8, (R8)
    16  	B		0(PC)
    17  
    18  TEXT runtime·open_trampoline(SB),NOSPLIT,$0
    19  	MOVW	4(R0), R1	// arg 2 mode
    20  	MOVW	8(R0), R2	// arg 3 perm
    21  	MOVW	0(R0), R0	// arg 1 name
    22  	BL	libc_open(SB)
    23  	RET
    24  
    25  TEXT runtime·close_trampoline(SB),NOSPLIT,$0
    26  	MOVW	0(R0), R0	// arg 1 fd
    27  	BL	libc_close(SB)
    28  	RET
    29  
    30  TEXT runtime·write_trampoline(SB),NOSPLIT,$0
    31  	MOVW	4(R0), R1	// arg 2 buf
    32  	MOVW	8(R0), R2	// arg 3 count
    33  	MOVW	0(R0), R0	// arg 1 fd
    34  	BL	libc_write(SB)
    35  	MOVW	$-1, R1
    36  	CMP	R0, R1
    37  	BNE	noerr
    38  	BL	libc_error(SB)
    39  	MOVW	(R0), R0
    40  	RSB	$0, R0, R0	// caller expects negative errno value
    41  noerr:
    42  	RET
    43  
    44  TEXT runtime·read_trampoline(SB),NOSPLIT,$0
    45  	MOVW	4(R0), R1	// arg 2 buf
    46  	MOVW	8(R0), R2	// arg 3 count
    47  	MOVW	0(R0), R0	// arg 1 fd
    48  	BL	libc_read(SB)
    49  	MOVW	$-1, R1
    50  	CMP	R0, R1
    51  	BNE	noerr
    52  	BL	libc_error(SB)
    53  	MOVW	(R0), R0
    54  	RSB	$0, R0, R0	// caller expects negative errno value
    55  noerr:
    56  	RET
    57  
    58  TEXT runtime·pipe_trampoline(SB),NOSPLIT,$0
    59  	BL	libc_pipe(SB)	// pointer already in R0
    60  	CMP	$0, R0
    61  	BEQ	3(PC)
    62  	BL	libc_error(SB)	// return negative errno value
    63  	RSB	$0, R0, R0
    64  	RET
    65  
    66  TEXT runtime·exit_trampoline(SB),NOSPLIT|NOFRAME,$0
    67  	MOVW	0(R0), R0	// arg 0 code
    68  	BL libc_exit(SB)
    69  	MOVW	$1234, R0
    70  	MOVW	$1002, R1
    71  	MOVW	R0, (R1)	// fail hard
    72  
    73  TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$0
    74  	MOVW	0(R0), R8	// signal
    75  	BL	libc_getpid(SB)
    76  	// arg 1 pid already in R0 from getpid
    77  	MOVW	R8, R1	// arg 2 signal
    78  	BL	libc_kill(SB)
    79  	RET
    80  
    81  TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
    82  	MOVW	R0, R8
    83  	MOVW	0(R8), R0	// arg 1 addr
    84  	MOVW	4(R8), R1	// arg 2 len
    85  	MOVW	8(R8), R2	// arg 3 prot
    86  	MOVW	12(R8), R3	// arg 4 flags
    87  	MOVW	16(R8), R4	// arg 5 fid
    88  	MOVW	20(R8), R5	// arg 6 offset
    89  	MOVW	$0, R6	// off_t is uint64_t
    90  	// Only R0-R3 are used for arguments, the rest
    91  	// go on the stack.
    92  	MOVM.DB.W [R4-R6], (R13)
    93  	BL	libc_mmap(SB)
    94  	ADD $12, R13
    95  	MOVW	$0, R1
    96  	MOVW	$-1, R2
    97  	CMP	R0, R2
    98  	BNE ok
    99  	BL	libc_error(SB)
   100  	MOVW	(R0), R1
   101  	MOVW	$0, R0
   102  ok:
   103  	MOVW	R0, 24(R8)	// ret 1 addr
   104  	MOVW	R1, 28(R8)	// ret 2 err
   105  	RET
   106  
   107  TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0
   108  	MOVW	4(R0), R1	// arg 2 len
   109  	MOVW	0(R0), R0	// arg 1 addr
   110  	BL libc_munmap(SB)
   111  	MOVW	$-1, R2
   112  	CMP	R0, R2
   113  	BL.EQ	notok<>(SB)
   114  	RET
   115  
   116  TEXT runtime·madvise_trampoline(SB),NOSPLIT,$0
   117  	MOVW	4(R0), R1	// arg 2 len
   118  	MOVW	8(R0), R2	// arg 3 advice
   119  	MOVW	0(R0), R0	// arg 1 addr
   120  	BL	libc_madvise(SB)
   121  	MOVW	$-1, R2
   122  	CMP	R0, R2
   123  	BL.EQ	notok<>(SB)
   124  	RET
   125  
   126  TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0
   127  	MOVW	4(R0), R1	// arg 2 new
   128  	MOVW	8(R0), R2	// arg 3 old
   129  	MOVW	0(R0), R0	// arg 1 which
   130  	BL	libc_setitimer(SB)
   131  	RET
   132  
   133  TEXT runtime·walltime_trampoline(SB),NOSPLIT,$0
   134  	// R0 already has *timeval
   135  	MOVW	$0, R1 // no timezone needed
   136  	BL	libc_gettimeofday(SB)
   137  	RET
   138  
   139  GLOBL timebase<>(SB),NOPTR,$(machTimebaseInfo__size)
   140  
   141  TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$0
   142  	MOVW	R0, R8
   143  	BL	libc_mach_absolute_time(SB)
   144  	MOVW	R0, 0(R8)
   145  	MOVW	R1, 4(R8)
   146  	MOVW	timebase<>+machTimebaseInfo_numer(SB), R6
   147  	MOVW	$timebase<>+machTimebaseInfo_denom(SB), R5
   148  	MOVW	(R5), R7
   149  	DMB	MB_ISH	// memory barrier for atomic read
   150  	CMP	$0, R7
   151  	BNE	initialized
   152  
   153  	SUB	$(machTimebaseInfo__size+7)/8*8, R13
   154  	MOVW	R13, R0
   155  	BL	libc_mach_timebase_info(SB)
   156  	MOVW	machTimebaseInfo_numer(R13), R6
   157  	MOVW	machTimebaseInfo_denom(R13), R7
   158  	ADD	$(machTimebaseInfo__size+7)/8*8, R13
   159  
   160  	MOVW	R6, timebase<>+machTimebaseInfo_numer(SB)
   161  	MOVW	$timebase<>+machTimebaseInfo_denom(SB), R5
   162  	DMB	MB_ISH	// memory barrier for atomic write
   163  	MOVW	R7, (R5)
   164  	DMB	MB_ISH
   165  
   166  initialized:
   167  	MOVW	R6, 8(R8)
   168  	MOVW	R7, 12(R8)
   169  	RET
   170  
   171  TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
   172  	MOVW	sig+4(FP), R0
   173  	MOVW	info+8(FP), R1
   174  	MOVW	ctx+12(FP), R2
   175  	MOVW	fn+0(FP), R11
   176  	MOVW	R13, R4
   177  	SUB	$24, R13
   178  	BIC	$0x7, R13 // alignment for ELF ABI
   179  	BL	(R11)
   180  	MOVW	R4, R13
   181  	RET
   182  
   183  TEXT runtime·sigtramp(SB),NOSPLIT,$0
   184  	// Reserve space for callee-save registers and arguments.
   185  	MOVM.DB.W [R4-R11], (R13)
   186  	SUB	$16, R13
   187  
   188  	// Save arguments.
   189  	MOVW	R0, 4(R13)	// sig
   190  	MOVW	R1, 8(R13)	// info
   191  	MOVW	R2, 12(R13)	// ctx
   192  
   193  	// this might be called in external code context,
   194  	// where g is not set.
   195  	MOVB	runtime·iscgo(SB), R0
   196  	CMP 	$0, R0
   197  	BL.NE	runtime·load_g(SB)
   198  
   199  	MOVW	R13, R6
   200  	CMP	$0, g
   201  	BEQ nog
   202  
   203  	// iOS always use the main stack to run the signal handler.
   204  	// We need to switch to gsignal ourselves.
   205  	MOVW	g_m(g), R11
   206  	MOVW	m_gsignal(R11), R5
   207  	MOVW	(g_stack+stack_hi)(R5), R6
   208  
   209  nog:
   210  	// Restore arguments.
   211  	MOVW	4(R13), R0
   212  	MOVW	8(R13), R1
   213  	MOVW	12(R13), R2
   214  
   215  	// Reserve space for args and the stack pointer on the
   216  	// gsignal stack.
   217  	SUB $24, R6
   218  	// Save stack pointer.
   219  	MOVW	R13, R4
   220  	MOVW	R4, 16(R6)
   221  	// Switch to gsignal stack.
   222  	MOVW	R6, R13
   223  
   224  	// Call sigtrampgo
   225  	MOVW	R0, 4(R13)
   226  	MOVW	R1, 8(R13)
   227  	MOVW	R2, 12(R13)
   228  	BL	runtime·sigtrampgo(SB)
   229  
   230  	// Switch to old stack.
   231  	MOVW	16(R13), R5
   232  	MOVW	R5, R13
   233  
   234  	// Restore callee-save registers.
   235  	ADD	$16, R13
   236  	MOVM.IA.W (R13), [R4-R11]
   237  
   238  	RET
   239  
   240  TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
   241  	JMP	runtime·sigtramp(SB)
   242  
   243  TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$0
   244  	MOVW	4(R0), R1	// arg 2 new
   245  	MOVW	8(R0), R2	// arg 3 old
   246  	MOVW	0(R0), R0	// arg 1 how
   247  	BL	libc_pthread_sigmask(SB)
   248  	CMP	$0, R0
   249  	BL.NE	notok<>(SB)
   250  	RET
   251  
   252  TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$0
   253  	MOVW	4(R0), R1	// arg 2 new
   254  	MOVW	8(R0), R2	// arg 3 old
   255  	MOVW	0(R0), R0	// arg 1 how
   256  	BL	libc_sigaction(SB)
   257  	RET
   258  
   259  TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0
   260  	MOVW	0(R0), R0	// arg 1 usec
   261  	BL libc_usleep(SB)
   262  	RET
   263  
   264  TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
   265  	B	runtime·armPublicationBarrier(SB)
   266  
   267  TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0
   268  	MOVW	4(R0), R1	// arg 2 miblen
   269  	MOVW	8(R0), R2	// arg 3 out
   270  	MOVW	12(R0), R3	// arg 4 size
   271  	MOVW	16(R0), R4	// arg 5 dst
   272  	MOVW	20(R0), R5	// arg 6 ndst
   273  	MOVW	0(R0), R0	// arg 1 mib
   274  	// Only R0-R3 are used for arguments, the rest
   275  	// go on the stack.
   276  	MOVM.DB.W [R4-R5], (R13)
   277  	BL	libc_sysctl(SB)
   278  	ADD $(2*4), R13
   279  	RET
   280  
   281  TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0
   282  	BL	libc_kqueue(SB)
   283  	RET
   284  
   285  // int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int events, Timespec *timeout)
   286  TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0
   287  	MOVW	4(R0), R1	// arg 2 keventss
   288  	MOVW	8(R0), R2	// arg 3 nch
   289  	MOVW	12(R0), R3	// arg 4 ev
   290  	MOVW	16(R0), R4	// arg 5 nev
   291  	MOVW	20(R0), R5	// arg 6 ts
   292  	MOVW	0(R0), R0	// arg 1 kq
   293  	// Only R0-R3 are used for arguments, the rest
   294  	// go on the stack.
   295  	MOVM.DB.W [R4-R5], (R13)
   296  	BL	libc_kevent(SB)
   297  	ADD	$(2*4), R13
   298  	MOVW	$-1, R2
   299  	CMP	R0, R2
   300  	BNE	ok
   301  	BL	libc_error(SB)
   302  	MOVW	(R0), R0	// errno
   303  	RSB	$0, R0, R0	// caller wants it as a negative error code
   304  ok:
   305  	RET
   306  
   307  TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0
   308  	MOVW	4(R0), R1	// arg 2 cmd
   309  	MOVW	8(R0), R2	// arg 3 arg
   310  	MOVW	0(R0), R0	// arg 1 fd
   311  	BL	libc_fcntl(SB)
   312  	RET
   313  
   314  // sigaltstack is not supported on iOS, so our sigtramp has
   315  // to do the stack switch ourselves.
   316  TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
   317  	MOVW	$43, R0
   318  	BL	libc_exit(SB)
   319  	RET
   320  
   321  // Thread related functions
   322  // Note: On darwin/arm, the runtime always use runtime/cgo to
   323  // create threads, so all thread related functions will just exit with a
   324  // unique status.
   325  
   326  TEXT runtime·mstart_stub(SB),NOSPLIT,$0
   327  	MOVW	$44, R0
   328  	BL	libc_exit(SB)
   329  	RET
   330  
   331  TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0
   332  	MOVW	$45, R0
   333  	BL	libc_exit(SB)
   334  	RET
   335  
   336  TEXT runtime·pthread_attr_getstacksize_trampoline(SB),NOSPLIT,$0
   337  	MOVW	$46, R0
   338  	BL	libc_exit(SB)
   339  	RET
   340  
   341  TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0
   342  	MOVW	$47, R0
   343  	BL	libc_exit(SB)
   344  	RET
   345  
   346  TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0
   347  	MOVW	$48, R0
   348  	BL	libc_exit(SB)
   349  	RET
   350  
   351  TEXT runtime·raise_trampoline(SB),NOSPLIT,$0
   352  	MOVW	0(R0), R0	// arg 1 sig
   353  	BL	libc_raise(SB)
   354  	RET
   355  
   356  TEXT runtime·pthread_mutex_init_trampoline(SB),NOSPLIT,$0
   357  	MOVW	4(R0), R1	// arg 2 attr
   358  	MOVW	0(R0), R0	// arg 1 mutex
   359  	BL	libc_pthread_mutex_init(SB)
   360  	RET
   361  
   362  TEXT runtime·pthread_mutex_lock_trampoline(SB),NOSPLIT,$0
   363  	MOVW	0(R0), R0	// arg 1 mutex
   364  	BL	libc_pthread_mutex_lock(SB)
   365  	RET
   366  
   367  TEXT runtime·pthread_mutex_unlock_trampoline(SB),NOSPLIT,$0
   368  	MOVW	0(R0), R0	// arg 1 mutex
   369  	BL	libc_pthread_mutex_unlock(SB)
   370  	RET
   371  
   372  TEXT runtime·pthread_cond_init_trampoline(SB),NOSPLIT,$0
   373  	MOVW	4(R0), R1	// arg 2 attr
   374  	MOVW	0(R0), R0	// arg 1 cond
   375  	BL	libc_pthread_cond_init(SB)
   376  	RET
   377  
   378  TEXT runtime·pthread_cond_wait_trampoline(SB),NOSPLIT,$0
   379  	MOVW	4(R0), R1	// arg 2 mutex
   380  	MOVW	0(R0), R0	// arg 1 cond
   381  	BL	libc_pthread_cond_wait(SB)
   382  	RET
   383  
   384  TEXT runtime·pthread_cond_timedwait_relative_np_trampoline(SB),NOSPLIT,$0
   385  	MOVW	4(R0), R1	// arg 2 mutex
   386  	MOVW	8(R0), R2	// arg 3 timeout
   387  	MOVW	0(R0), R0	// arg 1 cond
   388  	BL	libc_pthread_cond_timedwait_relative_np(SB)
   389  	RET
   390  
   391  TEXT runtime·pthread_cond_signal_trampoline(SB),NOSPLIT,$0
   392  	MOVW	0(R0), R0	// arg 1 cond
   393  	BL	libc_pthread_cond_signal(SB)
   394  	RET
   395  
   396  TEXT runtime·pthread_self_trampoline(SB),NOSPLIT,$0
   397  	MOVW	R0, R4		// R4 is callee-save
   398  	BL	libc_pthread_self(SB)
   399  	MOVW	R0, 0(R4)	// return value
   400  	RET
   401  
   402  TEXT runtime·pthread_kill_trampoline(SB),NOSPLIT,$0
   403  	MOVW	4(R0), R1	// arg 2 sig
   404  	MOVW	0(R0), R0	// arg 1 thread
   405  	BL	libc_pthread_kill(SB)
   406  	RET
   407  
   408  // syscall calls a function in libc on behalf of the syscall package.
   409  // syscall takes a pointer to a struct like:
   410  // struct {
   411  //	fn    uintptr
   412  //	a1    uintptr
   413  //	a2    uintptr
   414  //	a3    uintptr
   415  //	r1    uintptr
   416  //	r2    uintptr
   417  //	err   uintptr
   418  // }
   419  // syscall must be called on the g0 stack with the
   420  // C calling convention (use libcCall).
   421  TEXT runtime·syscall(SB),NOSPLIT,$0
   422  	MOVW.W	R0, -4(R13)	// push structure pointer
   423  	MOVW	0(R0), R12	// fn
   424  	MOVW	8(R0), R1	// a2
   425  	MOVW	12(R0), R2	// a3
   426  	MOVW	4(R0), R0	// a1
   427  	BL	(R12)
   428  	MOVW.P	4(R13), R2	// pop structure pointer
   429  	MOVW	R0, 16(R2)	// save r1
   430  	MOVW	R1, 20(R2)	// save r2
   431  	MOVW	$-1, R3
   432  	CMP	R0, R3
   433  	BNE	ok
   434  	MOVW.W	R2, -4(R13)	// push structure pointer
   435  	BL	libc_error(SB)
   436  	MOVW	(R0), R0
   437  	MOVW.P	4(R13), R2	// pop structure pointer
   438  	MOVW	R0, 24(R2)	// save err
   439  ok:
   440  	RET
   441  
   442  // syscallPtr is like syscall except the libc function reports an
   443  // error by returning NULL and setting errno.
   444  TEXT runtime·syscallPtr(SB),NOSPLIT,$0
   445  	MOVW.W	R0, -4(R13)	// push structure pointer
   446  	MOVW	0(R0), R12	// fn
   447  	MOVW	8(R0), R1	// a2
   448  	MOVW	12(R0), R2	// a3
   449  	MOVW	4(R0), R0	// a1
   450  	BL	(R12)
   451  	MOVW.P	4(R13), R2	// pop structure pointer
   452  	MOVW	R0, 16(R2)	// save r1
   453  	MOVW	R1, 20(R2)	// save r2
   454  	MOVW	$0, R3
   455  	CMP	R0, R3
   456  	BNE	ok
   457  	MOVW.W	R2, -4(R13)	// push structure pointer
   458  	BL	libc_error(SB)
   459  	MOVW	(R0), R0
   460  	MOVW.P	4(R13), R2	// pop structure pointer
   461  	MOVW	R0, 24(R2)	// save err
   462  ok:
   463  	RET
   464  
   465  // syscall6 calls a function in libc on behalf of the syscall package.
   466  // syscall6 takes a pointer to a struct like:
   467  // struct {
   468  //	fn    uintptr
   469  //	a1    uintptr
   470  //	a2    uintptr
   471  //	a3    uintptr
   472  //	a4    uintptr
   473  //	a5    uintptr
   474  //	a6    uintptr
   475  //	r1    uintptr
   476  //	r2    uintptr
   477  //	err   uintptr
   478  // }
   479  // syscall6 must be called on the g0 stack with the
   480  // C calling convention (use libcCall).
   481  TEXT runtime·syscall6(SB),NOSPLIT,$0
   482  	MOVW.W	R0, -4(R13)	// push structure pointer
   483  	MOVW	0(R0), R12	// fn
   484  	MOVW	24(R0), R1	// a6
   485  	MOVW.W	R1, -4(R13)
   486  	MOVW	20(R0), R1	// a5
   487  	MOVW.W	R1, -4(R13)
   488  	MOVW	8(R0), R1	// a2
   489  	MOVW	12(R0), R2	// a3
   490  	MOVW	16(R0), R3	// a4
   491  	MOVW	4(R0), R0	// a1
   492  	BL	(R12)
   493  	ADD	$8, R13
   494  	MOVW.P	4(R13), R2	// pop structure pointer
   495  	MOVW	R0, 28(R2)	// save r1
   496  	MOVW	R1, 32(R2)	// save r2
   497  	MOVW	$-1, R3
   498  	CMP	R0, R3
   499  	BNE	ok
   500  	MOVW.W	R2, -4(R13)	// push structure pointer
   501  	BL	libc_error(SB)
   502  	MOVW	(R0), R0
   503  	MOVW.P	4(R13), R2	// pop structure pointer
   504  	MOVW	R0, 36(R2)	// save err
   505  ok:
   506  	RET
   507  
   508  // syscall6X calls a function in libc on behalf of the syscall package.
   509  // syscall6X takes a pointer to a struct like:
   510  // struct {
   511  //	fn    uintptr
   512  //	a1    uintptr
   513  //	a2    uintptr
   514  //	a3    uintptr
   515  //	a4    uintptr
   516  //	a5    uintptr
   517  //	a6    uintptr
   518  //	r1    uintptr
   519  //	r2    uintptr
   520  //	err   uintptr
   521  // }
   522  // syscall6X must be called on the g0 stack with the
   523  // C calling convention (use libcCall).
   524  TEXT runtime·syscall6X(SB),NOSPLIT,$0
   525  	MOVW.W	R0, -4(R13)	// push structure pointer
   526  	MOVW	0(R0), R12	// fn
   527  	MOVW	24(R0), R1	// a6
   528  	MOVW.W	R1, -4(R13)
   529  	MOVW	20(R0), R1	// a5
   530  	MOVW.W	R1, -4(R13)
   531  	MOVW	8(R0), R1	// a2
   532  	MOVW	12(R0), R2	// a3
   533  	MOVW	16(R0), R3	// a4
   534  	MOVW	4(R0), R0	// a1
   535  	BL	(R12)
   536  	ADD	$8, R13
   537  	MOVW.P	4(R13), R2	// pop structure pointer
   538  	MOVW	R0, 28(R2)	// save r1
   539  	MOVW	R1, 32(R2)	// save r2
   540  	MOVW	$-1, R3
   541  	CMP	R0, R3
   542  	BNE	ok
   543  	CMP	R1, R3
   544  	BNE	ok
   545  	MOVW.W	R2, -4(R13)	// push structure pointer
   546  	BL	libc_error(SB)
   547  	MOVW	(R0), R0
   548  	MOVW.P	4(R13), R2	// pop structure pointer
   549  	MOVW	R0, 36(R2)	// save err
   550  ok:
   551  	RET
   552  
   553  // syscall9 calls a function in libc on behalf of the syscall package.
   554  // syscall9 takes a pointer to a struct like:
   555  // struct {
   556  //	fn    uintptr
   557  //	a1    uintptr
   558  //	a2    uintptr
   559  //	a3    uintptr
   560  //	a4    uintptr
   561  //	a5    uintptr
   562  //	a6    uintptr
   563  //	a7    uintptr
   564  //	a8    uintptr
   565  //	a9    uintptr
   566  //	r1    uintptr
   567  //	r2    uintptr
   568  //	err   uintptr
   569  // }
   570  // syscall9 must be called on the g0 stack with the
   571  // C calling convention (use libcCall).
   572  TEXT runtime·syscall9(SB),NOSPLIT,$0
   573  	MOVW.W	R0, -4(R13)	// push structure pointer
   574  	MOVW	0(R0), R12	// fn
   575  	MOVW	36(R0), R1	// a9
   576  	MOVW.W	R1, -4(R13)
   577  	MOVW	32(R0), R1	// a8
   578  	MOVW.W	R1, -4(R13)
   579  	MOVW	28(R0), R1	// a7
   580  	MOVW.W	R1, -4(R13)
   581  	MOVW	24(R0), R1	// a6
   582  	MOVW.W	R1, -4(R13)
   583  	MOVW	20(R0), R1	// a5
   584  	MOVW.W	R1, -4(R13)
   585  	MOVW	8(R0), R1	// a2
   586  	MOVW	12(R0), R2	// a3
   587  	MOVW	16(R0), R3	// a4
   588  	MOVW	4(R0), R0	// a1
   589  	BL	(R12)
   590  	ADD	$20, R13
   591  	MOVW.P	4(R13), R2	// pop structure pointer
   592  	MOVW	R0, 40(R2)	// save r1
   593  	MOVW	R1, 44(R2)	// save r2
   594  	MOVW	$-1, R3
   595  	CMP	R0, R3
   596  	BNE	ok
   597  	MOVW.W	R2, -4(R13)	// push structure pointer
   598  	BL	libc_error(SB)
   599  	MOVW	(R0), R0
   600  	MOVW.P	4(R13), R2	// pop structure pointer
   601  	MOVW	R0, 48(R2)	// save err
   602  ok:
   603  	RET