summaryrefslogtreecommitdiffstats
path: root/src/runtime/sys_darwin_arm64.s
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 13:14:23 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 13:14:23 +0000
commit73df946d56c74384511a194dd01dbe099584fd1a (patch)
treefd0bcea490dd81327ddfbb31e215439672c9a068 /src/runtime/sys_darwin_arm64.s
parentInitial commit. (diff)
downloadgolang-1.16-73df946d56c74384511a194dd01dbe099584fd1a.tar.xz
golang-1.16-73df946d56c74384511a194dd01dbe099584fd1a.zip
Adding upstream version 1.16.10.upstream/1.16.10upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/runtime/sys_darwin_arm64.s')
-rw-r--r--src/runtime/sys_darwin_arm64.s757
1 files changed, 757 insertions, 0 deletions
diff --git a/src/runtime/sys_darwin_arm64.s b/src/runtime/sys_darwin_arm64.s
new file mode 100644
index 0000000..96d2ed1
--- /dev/null
+++ b/src/runtime/sys_darwin_arm64.s
@@ -0,0 +1,757 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// System calls and other sys.stuff for ARM64, Darwin
+// System calls are implemented in libSystem, this file contains
+// trampolines that convert from Go to C calling convention.
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "textflag.h"
+
+#define CLOCK_REALTIME 0
+
+TEXT notok<>(SB),NOSPLIT,$0
+ MOVD $0, R8
+ MOVD R8, (R8)
+ B 0(PC)
+
+TEXT runtime·open_trampoline(SB),NOSPLIT,$0
+ SUB $16, RSP
+ MOVW 8(R0), R1 // arg 2 flags
+ MOVW 12(R0), R2 // arg 3 mode
+ MOVW R2, (RSP) // arg 3 is variadic, pass on stack
+ MOVD 0(R0), R0 // arg 1 pathname
+ BL libc_open(SB)
+ ADD $16, RSP
+ RET
+
+TEXT runtime·close_trampoline(SB),NOSPLIT,$0
+ MOVW 0(R0), R0 // arg 1 fd
+ BL libc_close(SB)
+ RET
+
+TEXT runtime·write_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 buf
+ MOVW 16(R0), R2 // arg 3 count
+ MOVW 0(R0), R0 // arg 1 fd
+ BL libc_write(SB)
+ MOVD $-1, R1
+ CMP R0, R1
+ BNE noerr
+ BL libc_error(SB)
+ MOVW (R0), R0
+ NEG R0, R0 // caller expects negative errno value
+noerr:
+ RET
+
+TEXT runtime·read_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 buf
+ MOVW 16(R0), R2 // arg 3 count
+ MOVW 0(R0), R0 // arg 1 fd
+ BL libc_read(SB)
+ MOVD $-1, R1
+ CMP R0, R1
+ BNE noerr
+ BL libc_error(SB)
+ MOVW (R0), R0
+ NEG R0, R0 // caller expects negative errno value
+noerr:
+ RET
+
+TEXT runtime·pipe_trampoline(SB),NOSPLIT,$0
+ BL libc_pipe(SB) // pointer already in R0
+ CMP $0, R0
+ BEQ 3(PC)
+ BL libc_error(SB) // return negative errno value
+ NEG R0, R0
+ RET
+
+TEXT runtime·exit_trampoline(SB),NOSPLIT|NOFRAME,$0
+ MOVW 0(R0), R0
+ BL libc_exit(SB)
+ MOVD $1234, R0
+ MOVD $1002, R1
+ MOVD R0, (R1) // fail hard
+
+TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$0
+ MOVD 0(R0), R19 // signal
+ BL libc_getpid(SB)
+ // arg 1 pid already in R0 from getpid
+ MOVD R19, R1 // arg 2 signal
+ BL libc_kill(SB)
+ RET
+
+TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
+ MOVD R0, R19
+ MOVD 0(R19), R0 // arg 1 addr
+ MOVD 8(R19), R1 // arg 2 len
+ MOVW 16(R19), R2 // arg 3 prot
+ MOVW 20(R19), R3 // arg 4 flags
+ MOVW 24(R19), R4 // arg 5 fd
+ MOVW 28(R19), R5 // arg 6 off
+ BL libc_mmap(SB)
+ MOVD $0, R1
+ MOVD $-1, R2
+ CMP R0, R2
+ BNE ok
+ BL libc_error(SB)
+ MOVW (R0), R1
+ MOVD $0, R0
+ok:
+ MOVD R0, 32(R19) // ret 1 p
+ MOVD R1, 40(R19) // ret 2 err
+ RET
+
+TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 len
+ MOVD 0(R0), R0 // arg 1 addr
+ BL libc_munmap(SB)
+ CMP $0, R0
+ BEQ 2(PC)
+ BL notok<>(SB)
+ RET
+
+TEXT runtime·madvise_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 len
+ MOVW 16(R0), R2 // arg 3 advice
+ MOVD 0(R0), R0 // arg 1 addr
+ BL libc_madvise(SB)
+ RET
+
+TEXT runtime·mlock_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 len
+ MOVD 0(R0), R0 // arg 1 addr
+ BL libc_mlock(SB)
+ RET
+
+TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 new
+ MOVD 16(R0), R2 // arg 3 old
+ MOVW 0(R0), R0 // arg 1 which
+ BL libc_setitimer(SB)
+ RET
+
+TEXT runtime·walltime_trampoline(SB),NOSPLIT,$0
+ MOVD R0, R1 // arg 2 timespec
+ MOVW $CLOCK_REALTIME, R0 // arg 1 clock_id
+ BL libc_clock_gettime(SB)
+ RET
+
+GLOBL timebase<>(SB),NOPTR,$(machTimebaseInfo__size)
+
+TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$40
+ MOVD R0, R19
+ BL libc_mach_absolute_time(SB)
+ MOVD R0, 0(R19)
+ MOVW timebase<>+machTimebaseInfo_numer(SB), R20
+ MOVD $timebase<>+machTimebaseInfo_denom(SB), R21
+ LDARW (R21), R21 // atomic read
+ CMP $0, R21
+ BNE initialized
+
+ SUB $(machTimebaseInfo__size+15)/16*16, RSP
+ MOVD RSP, R0
+ BL libc_mach_timebase_info(SB)
+ MOVW machTimebaseInfo_numer(RSP), R20
+ MOVW machTimebaseInfo_denom(RSP), R21
+ ADD $(machTimebaseInfo__size+15)/16*16, RSP
+
+ MOVW R20, timebase<>+machTimebaseInfo_numer(SB)
+ MOVD $timebase<>+machTimebaseInfo_denom(SB), R22
+ STLRW R21, (R22) // atomic write
+
+initialized:
+ MOVW R20, 8(R19)
+ MOVW R21, 12(R19)
+ RET
+
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
+ MOVW sig+8(FP), R0
+ MOVD info+16(FP), R1
+ MOVD ctx+24(FP), R2
+ MOVD fn+0(FP), R11
+ BL (R11)
+ RET
+
+TEXT runtime·sigtramp(SB),NOSPLIT,$192
+ // Save callee-save registers in the case of signal forwarding.
+ // Please refer to https://golang.org/issue/31827 .
+ MOVD R19, 8*4(RSP)
+ MOVD R20, 8*5(RSP)
+ MOVD R21, 8*6(RSP)
+ MOVD R22, 8*7(RSP)
+ MOVD R23, 8*8(RSP)
+ MOVD R24, 8*9(RSP)
+ MOVD R25, 8*10(RSP)
+ MOVD R26, 8*11(RSP)
+ MOVD R27, 8*12(RSP)
+ MOVD g, 8*13(RSP)
+ MOVD R29, 8*14(RSP)
+ FMOVD F8, 8*15(RSP)
+ FMOVD F9, 8*16(RSP)
+ FMOVD F10, 8*17(RSP)
+ FMOVD F11, 8*18(RSP)
+ FMOVD F12, 8*19(RSP)
+ FMOVD F13, 8*20(RSP)
+ FMOVD F14, 8*21(RSP)
+ FMOVD F15, 8*22(RSP)
+
+ // Save arguments.
+ MOVW R0, (8*1)(RSP) // sig
+ MOVD R1, (8*2)(RSP) // info
+ MOVD R2, (8*3)(RSP) // ctx
+
+ // this might be called in external code context,
+ // where g is not set.
+ BL runtime·load_g(SB)
+
+#ifdef GOOS_ios
+ MOVD RSP, R6
+ CMP $0, g
+ BEQ nog
+ // iOS always use the main stack to run the signal handler.
+ // We need to switch to gsignal ourselves.
+ MOVD g_m(g), R11
+ MOVD m_gsignal(R11), R5
+ MOVD (g_stack+stack_hi)(R5), R6
+
+nog:
+ // Restore arguments.
+ MOVW (8*1)(RSP), R0
+ MOVD (8*2)(RSP), R1
+ MOVD (8*3)(RSP), R2
+
+ // Reserve space for args and the stack pointer on the
+ // gsignal stack.
+ SUB $48, R6
+ // Save stack pointer.
+ MOVD RSP, R4
+ MOVD R4, (8*4)(R6)
+ // Switch to gsignal stack.
+ MOVD R6, RSP
+
+ // Save arguments.
+ MOVW R0, (8*1)(RSP)
+ MOVD R1, (8*2)(RSP)
+ MOVD R2, (8*3)(RSP)
+#endif
+
+ // Call sigtrampgo.
+ MOVD $runtime·sigtrampgo(SB), R11
+ BL (R11)
+
+#ifdef GOOS_ios
+ // Switch to old stack.
+ MOVD (8*4)(RSP), R5
+ MOVD R5, RSP
+#endif
+
+ // Restore callee-save registers.
+ MOVD (8*4)(RSP), R19
+ MOVD (8*5)(RSP), R20
+ MOVD (8*6)(RSP), R21
+ MOVD (8*7)(RSP), R22
+ MOVD (8*8)(RSP), R23
+ MOVD (8*9)(RSP), R24
+ MOVD (8*10)(RSP), R25
+ MOVD (8*11)(RSP), R26
+ MOVD (8*12)(RSP), R27
+ MOVD (8*13)(RSP), g
+ MOVD (8*14)(RSP), R29
+ FMOVD (8*15)(RSP), F8
+ FMOVD (8*16)(RSP), F9
+ FMOVD (8*17)(RSP), F10
+ FMOVD (8*18)(RSP), F11
+ FMOVD (8*19)(RSP), F12
+ FMOVD (8*20)(RSP), F13
+ FMOVD (8*21)(RSP), F14
+ FMOVD (8*22)(RSP), F15
+
+ RET
+
+TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
+ JMP runtime·sigtramp(SB)
+
+TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 new
+ MOVD 16(R0), R2 // arg 3 old
+ MOVW 0(R0), R0 // arg 1 how
+ BL libc_pthread_sigmask(SB)
+ CMP $0, R0
+ BEQ 2(PC)
+ BL notok<>(SB)
+ RET
+
+TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 new
+ MOVD 16(R0), R2 // arg 3 old
+ MOVW 0(R0), R0 // arg 1 how
+ BL libc_sigaction(SB)
+ CMP $0, R0
+ BEQ 2(PC)
+ BL notok<>(SB)
+ RET
+
+TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0
+ MOVW 0(R0), R0 // arg 1 usec
+ BL libc_usleep(SB)
+ RET
+
+TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0
+ MOVW 8(R0), R1 // arg 2 miblen
+ MOVD 16(R0), R2 // arg 3 oldp
+ MOVD 24(R0), R3 // arg 4 oldlenp
+ MOVD 32(R0), R4 // arg 5 newp
+ MOVD 40(R0), R5 // arg 6 newlen
+ MOVD 0(R0), R0 // arg 1 mib
+ BL libc_sysctl(SB)
+ RET
+
+TEXT runtime·sysctlbyname_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 oldp
+ MOVD 16(R0), R2 // arg 3 oldlenp
+ MOVD 24(R0), R3 // arg 4 newp
+ MOVD 32(R0), R4 // arg 5 newlen
+ MOVD 0(R0), R0 // arg 1 name
+ BL libc_sysctlbyname(SB)
+ RET
+
+
+TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0
+ BL libc_kqueue(SB)
+ RET
+
+TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 keventt
+ MOVW 16(R0), R2 // arg 3 nch
+ MOVD 24(R0), R3 // arg 4 ev
+ MOVW 32(R0), R4 // arg 5 nev
+ MOVD 40(R0), R5 // arg 6 ts
+ MOVW 0(R0), R0 // arg 1 kq
+ BL libc_kevent(SB)
+ MOVD $-1, R2
+ CMP R0, R2
+ BNE ok
+ BL libc_error(SB)
+ MOVW (R0), R0 // errno
+ NEG R0, R0 // caller wants it as a negative error code
+ok:
+ RET
+
+TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0
+ SUB $16, RSP
+ MOVW 4(R0), R1 // arg 2 cmd
+ MOVW 8(R0), R2 // arg 3 arg
+ MOVW R2, (RSP) // arg 3 is variadic, pass on stack
+ MOVW 0(R0), R0 // arg 1 fd
+ BL libc_fcntl(SB)
+ ADD $16, RSP
+ RET
+
+TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
+#ifdef GOOS_ios
+ // sigaltstack on iOS is not supported and will always
+ // run the signal handler on the main stack, so our sigtramp has
+ // to do the stack switch ourselves.
+ MOVW $43, R0
+ BL libc_exit(SB)
+#else
+ MOVD 8(R0), R1 // arg 2 old
+ MOVD 0(R0), R0 // arg 1 new
+ CALL libc_sigaltstack(SB)
+ CBZ R0, 2(PC)
+ BL notok<>(SB)
+#endif
+ RET
+
+// Thread related functions
+
+// mstart_stub is the first function executed on a new thread started by pthread_create.
+// It just does some low-level setup and then calls mstart.
+// Note: called with the C calling convention.
+TEXT runtime·mstart_stub(SB),NOSPLIT,$160
+ // R0 points to the m.
+ // We are already on m's g0 stack.
+
+ // Save callee-save registers.
+ MOVD R19, 8(RSP)
+ MOVD R20, 16(RSP)
+ MOVD R21, 24(RSP)
+ MOVD R22, 32(RSP)
+ MOVD R23, 40(RSP)
+ MOVD R24, 48(RSP)
+ MOVD R25, 56(RSP)
+ MOVD R26, 64(RSP)
+ MOVD R27, 72(RSP)
+ MOVD g, 80(RSP)
+ MOVD R29, 88(RSP)
+ FMOVD F8, 96(RSP)
+ FMOVD F9, 104(RSP)
+ FMOVD F10, 112(RSP)
+ FMOVD F11, 120(RSP)
+ FMOVD F12, 128(RSP)
+ FMOVD F13, 136(RSP)
+ FMOVD F14, 144(RSP)
+ FMOVD F15, 152(RSP)
+
+ MOVD m_g0(R0), g
+ BL ·save_g(SB)
+
+ BL runtime·mstart(SB)
+
+ // Restore callee-save registers.
+ MOVD 8(RSP), R19
+ MOVD 16(RSP), R20
+ MOVD 24(RSP), R21
+ MOVD 32(RSP), R22
+ MOVD 40(RSP), R23
+ MOVD 48(RSP), R24
+ MOVD 56(RSP), R25
+ MOVD 64(RSP), R26
+ MOVD 72(RSP), R27
+ MOVD 80(RSP), g
+ MOVD 88(RSP), R29
+ FMOVD 96(RSP), F8
+ FMOVD 104(RSP), F9
+ FMOVD 112(RSP), F10
+ FMOVD 120(RSP), F11
+ FMOVD 128(RSP), F12
+ FMOVD 136(RSP), F13
+ FMOVD 144(RSP), F14
+ FMOVD 152(RSP), F15
+
+ // Go is all done with this OS thread.
+ // Tell pthread everything is ok (we never join with this thread, so
+ // the value here doesn't really matter).
+ MOVD $0, R0
+
+ RET
+
+TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0
+ MOVD 0(R0), R0 // arg 1 attr
+ BL libc_pthread_attr_init(SB)
+ RET
+
+TEXT runtime·pthread_attr_getstacksize_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 size
+ MOVD 0(R0), R0 // arg 1 attr
+ BL libc_pthread_attr_getstacksize(SB)
+ RET
+
+TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 state
+ MOVD 0(R0), R0 // arg 1 attr
+ BL libc_pthread_attr_setdetachstate(SB)
+ RET
+
+TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0
+ SUB $16, RSP
+ MOVD 0(R0), R1 // arg 2 state
+ MOVD 8(R0), R2 // arg 3 start
+ MOVD 16(R0), R3 // arg 4 arg
+ MOVD RSP, R0 // arg 1 &threadid (which we throw away)
+ BL libc_pthread_create(SB)
+ ADD $16, RSP
+ RET
+
+TEXT runtime·raise_trampoline(SB),NOSPLIT,$0
+ MOVW 0(R0), R0 // arg 1 sig
+ BL libc_raise(SB)
+ RET
+
+TEXT runtime·pthread_mutex_init_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 attr
+ MOVD 0(R0), R0 // arg 1 mutex
+ BL libc_pthread_mutex_init(SB)
+ RET
+
+TEXT runtime·pthread_mutex_lock_trampoline(SB),NOSPLIT,$0
+ MOVD 0(R0), R0 // arg 1 mutex
+ BL libc_pthread_mutex_lock(SB)
+ RET
+
+TEXT runtime·pthread_mutex_unlock_trampoline(SB),NOSPLIT,$0
+ MOVD 0(R0), R0 // arg 1 mutex
+ BL libc_pthread_mutex_unlock(SB)
+ RET
+
+TEXT runtime·pthread_cond_init_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 attr
+ MOVD 0(R0), R0 // arg 1 cond
+ BL libc_pthread_cond_init(SB)
+ RET
+
+TEXT runtime·pthread_cond_wait_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 mutex
+ MOVD 0(R0), R0 // arg 1 cond
+ BL libc_pthread_cond_wait(SB)
+ RET
+
+TEXT runtime·pthread_cond_timedwait_relative_np_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 mutex
+ MOVD 16(R0), R2 // arg 3 timeout
+ MOVD 0(R0), R0 // arg 1 cond
+ BL libc_pthread_cond_timedwait_relative_np(SB)
+ RET
+
+TEXT runtime·pthread_cond_signal_trampoline(SB),NOSPLIT,$0
+ MOVD 0(R0), R0 // arg 1 cond
+ BL libc_pthread_cond_signal(SB)
+ RET
+
+TEXT runtime·pthread_self_trampoline(SB),NOSPLIT,$0
+ MOVD R0, R19 // R19 is callee-save
+ BL libc_pthread_self(SB)
+ MOVD R0, 0(R19) // return value
+ RET
+
+TEXT runtime·pthread_kill_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 sig
+ MOVD 0(R0), R0 // arg 1 thread
+ BL libc_pthread_kill(SB)
+ RET
+
+TEXT runtime·pthread_key_create_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 destructor
+ MOVD 0(R0), R0 // arg 1 *key
+ BL libc_pthread_key_create(SB)
+ RET
+
+TEXT runtime·pthread_setspecific_trampoline(SB),NOSPLIT,$0
+ MOVD 8(R0), R1 // arg 2 value
+ MOVD 0(R0), R0 // arg 1 key
+ BL libc_pthread_setspecific(SB)
+ RET
+
+// syscall calls a function in libc on behalf of the syscall package.
+// syscall takes a pointer to a struct like:
+// struct {
+// fn uintptr
+// a1 uintptr
+// a2 uintptr
+// a3 uintptr
+// r1 uintptr
+// r2 uintptr
+// err uintptr
+// }
+// syscall must be called on the g0 stack with the
+// C calling convention (use libcCall).
+TEXT runtime·syscall(SB),NOSPLIT,$0
+ SUB $16, RSP // push structure pointer
+ MOVD R0, 8(RSP)
+
+ MOVD 0(R0), R12 // fn
+ MOVD 16(R0), R1 // a2
+ MOVD 24(R0), R2 // a3
+ MOVD 8(R0), R0 // a1
+
+ // If fn is declared as vararg, we have to pass the vararg arguments on the stack.
+ // (Because ios decided not to adhere to the standard arm64 calling convention, sigh...)
+ // The only libSystem calls we support that are vararg are open, fcntl, and ioctl,
+ // which are all of the form fn(x, y, ...). So we just need to put the 3rd arg
+ // on the stack as well.
+ // If we ever have other vararg libSystem calls, we might need to handle more cases.
+ MOVD R2, (RSP)
+
+ BL (R12)
+
+ MOVD 8(RSP), R2 // pop structure pointer
+ ADD $16, RSP
+ MOVD R0, 32(R2) // save r1
+ MOVD R1, 40(R2) // save r2
+ CMPW $-1, R0
+ BNE ok
+ SUB $16, RSP // push structure pointer
+ MOVD R2, 8(RSP)
+ BL libc_error(SB)
+ MOVW (R0), R0
+ MOVD 8(RSP), R2 // pop structure pointer
+ ADD $16, RSP
+ MOVD R0, 48(R2) // save err
+ok:
+ RET
+
+// syscallX calls a function in libc on behalf of the syscall package.
+// syscallX takes a pointer to a struct like:
+// struct {
+// fn uintptr
+// a1 uintptr
+// a2 uintptr
+// a3 uintptr
+// r1 uintptr
+// r2 uintptr
+// err uintptr
+// }
+// syscallX must be called on the g0 stack with the
+// C calling convention (use libcCall).
+TEXT runtime·syscallX(SB),NOSPLIT,$0
+ SUB $16, RSP // push structure pointer
+ MOVD R0, (RSP)
+
+ MOVD 0(R0), R12 // fn
+ MOVD 16(R0), R1 // a2
+ MOVD 24(R0), R2 // a3
+ MOVD 8(R0), R0 // a1
+ BL (R12)
+
+ MOVD (RSP), R2 // pop structure pointer
+ ADD $16, RSP
+ MOVD R0, 32(R2) // save r1
+ MOVD R1, 40(R2) // save r2
+ CMP $-1, R0
+ BNE ok
+ SUB $16, RSP // push structure pointer
+ MOVD R2, (RSP)
+ BL libc_error(SB)
+ MOVW (R0), R0
+ MOVD (RSP), R2 // pop structure pointer
+ ADD $16, RSP
+ MOVD R0, 48(R2) // save err
+ok:
+ RET
+
+// syscallPtr is like syscallX except that the libc function reports an
+// error by returning NULL and setting errno.
+TEXT runtime·syscallPtr(SB),NOSPLIT,$0
+ SUB $16, RSP // push structure pointer
+ MOVD R0, (RSP)
+
+ MOVD 0(R0), R12 // fn
+ MOVD 16(R0), R1 // a2
+ MOVD 24(R0), R2 // a3
+ MOVD 8(R0), R0 // a1
+ BL (R12)
+
+ MOVD (RSP), R2 // pop structure pointer
+ ADD $16, RSP
+ MOVD R0, 32(R2) // save r1
+ MOVD R1, 40(R2) // save r2
+ CMP $0, R0
+ BNE ok
+ SUB $16, RSP // push structure pointer
+ MOVD R2, (RSP)
+ BL libc_error(SB)
+ MOVW (R0), R0
+ MOVD (RSP), R2 // pop structure pointer
+ ADD $16, RSP
+ MOVD R0, 48(R2) // save err
+ok:
+ RET
+
+// syscall6 calls a function in libc on behalf of the syscall package.
+// syscall6 takes a pointer to a struct like:
+// struct {
+// fn uintptr
+// a1 uintptr
+// a2 uintptr
+// a3 uintptr
+// a4 uintptr
+// a5 uintptr
+// a6 uintptr
+// r1 uintptr
+// r2 uintptr
+// err uintptr
+// }
+// syscall6 must be called on the g0 stack with the
+// C calling convention (use libcCall).
+TEXT runtime·syscall6(SB),NOSPLIT,$0
+ SUB $16, RSP // push structure pointer
+ MOVD R0, 8(RSP)
+
+ MOVD 0(R0), R12 // fn
+ MOVD 16(R0), R1 // a2
+ MOVD 24(R0), R2 // a3
+ MOVD 32(R0), R3 // a4
+ MOVD 40(R0), R4 // a5
+ MOVD 48(R0), R5 // a6
+ MOVD 8(R0), R0 // a1
+
+ // If fn is declared as vararg, we have to pass the vararg arguments on the stack.
+ // See syscall above. The only function this applies to is openat, for which the 4th
+ // arg must be on the stack.
+ MOVD R3, (RSP)
+
+ BL (R12)
+
+ MOVD 8(RSP), R2 // pop structure pointer
+ ADD $16, RSP
+ MOVD R0, 56(R2) // save r1
+ MOVD R1, 64(R2) // save r2
+ CMPW $-1, R0
+ BNE ok
+ SUB $16, RSP // push structure pointer
+ MOVD R2, 8(RSP)
+ BL libc_error(SB)
+ MOVW (R0), R0
+ MOVD 8(RSP), R2 // pop structure pointer
+ ADD $16, RSP
+ MOVD R0, 72(R2) // save err
+ok:
+ RET
+
+// syscall6X calls a function in libc on behalf of the syscall package.
+// syscall6X takes a pointer to a struct like:
+// struct {
+// fn uintptr
+// a1 uintptr
+// a2 uintptr
+// a3 uintptr
+// a4 uintptr
+// a5 uintptr
+// a6 uintptr
+// r1 uintptr
+// r2 uintptr
+// err uintptr
+// }
+// syscall6X must be called on the g0 stack with the
+// C calling convention (use libcCall).
+TEXT runtime·syscall6X(SB),NOSPLIT,$0
+ SUB $16, RSP // push structure pointer
+ MOVD R0, (RSP)
+
+ MOVD 0(R0), R12 // fn
+ MOVD 16(R0), R1 // a2
+ MOVD 24(R0), R2 // a3
+ MOVD 32(R0), R3 // a4
+ MOVD 40(R0), R4 // a5
+ MOVD 48(R0), R5 // a6
+ MOVD 8(R0), R0 // a1
+ BL (R12)
+
+ MOVD (RSP), R2 // pop structure pointer
+ ADD $16, RSP
+ MOVD R0, 56(R2) // save r1
+ MOVD R1, 64(R2) // save r2
+ CMP $-1, R0
+ BNE ok
+ SUB $16, RSP // push structure pointer
+ MOVD R2, (RSP)
+ BL libc_error(SB)
+ MOVW (R0), R0
+ MOVD (RSP), R2 // pop structure pointer
+ ADD $16, RSP
+ MOVD R0, 72(R2) // save err
+ok:
+ RET
+
+// syscallNoErr is like syscall6 but does not check for errors, and
+// only returns one value, for use with standard C ABI library functions.
+TEXT runtime·syscallNoErr(SB),NOSPLIT,$0
+ SUB $16, RSP // push structure pointer
+ MOVD R0, (RSP)
+
+ MOVD 0(R0), R12 // fn
+ MOVD 16(R0), R1 // a2
+ MOVD 24(R0), R2 // a3
+ MOVD 32(R0), R3 // a4
+ MOVD 40(R0), R4 // a5
+ MOVD 48(R0), R5 // a6
+ MOVD 8(R0), R0 // a1
+ BL (R12)
+
+ MOVD (RSP), R2 // pop structure pointer
+ ADD $16, RSP
+ MOVD R0, 56(R2) // save r1
+ RET