mirror of
https://github.com/golang/go
synced 2024-11-19 04:24:39 -07:00
c485e8b559
The implementation of semaphores, and therefore notes, used on Darwin is not async-signal-safe. The runtime has one case where a note needs to be woken up from a signal handler: the call to notewakeup in sigsend. That notewakeup call is only called on a single note, and it doesn't need the full functionality of notes: nothing ever does a timed wait on it. So change that one note to use a different implementation on Darwin, based on a pipe. This lets the wakeup code use the write call, which is async-signal-safe. Fixes #31264 Change-Id: If705072d7a961dd908ea9d639c8d12b222c64806 Reviewed-on: https://go-review.googlesource.com/c/go/+/184169 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
670 lines
15 KiB
ArmAsm
670 lines
15 KiB
ArmAsm
// 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"
|
|
|
|
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)
|
|
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)
|
|
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·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
|
|
// R0 already has *timeval
|
|
MOVD $0, R1 // no timezone needed
|
|
BL libc_gettimeofday(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.
|
|
MOVB runtime·iscgo(SB), R0
|
|
CMP $0, R0
|
|
BEQ 2(PC)
|
|
BL runtime·load_g(SB)
|
|
|
|
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
|
|
|
|
// Call sigtrampgo.
|
|
MOVW R0, (8*1)(RSP)
|
|
MOVD R1, (8*2)(RSP)
|
|
MOVD R2, (8*3)(RSP)
|
|
MOVD $runtime·sigtrampgo(SB), R11
|
|
BL (R11)
|
|
|
|
// Switch to old stack.
|
|
MOVD (8*4)(RSP), R5
|
|
MOVD R5, RSP
|
|
|
|
// 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 out
|
|
MOVD 24(R0), R3 // arg 4 size
|
|
MOVD 32(R0), R4 // arg 5 dst
|
|
MOVD 40(R0), R5 // arg 6 ndst
|
|
MOVD 0(R0), R0 // arg 1 mib
|
|
BL libc_sysctl(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
|
|
|
|
// 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.
|
|
TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
|
|
MOVW $43, R0
|
|
BL libc_exit(SB)
|
|
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 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
|
|
|
|
// 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
|