mirror of
https://github.com/golang/go
synced 2024-11-07 14:56:16 -07:00
7ad496b6f5
The previous CL introduced macros for transitions from the Windows ABI to the Go ABI. This CL does the same for SysV and uses them in almost all places where we transition from the C ABI to the Go ABI. Compared to Windows, this transition is much simpler and I didn't find any places that were getting it wrong. But this does let us unify a lot of code nicely and introduces some degree of abstraction around these ABI transitions. Change-Id: Ib6bdecafce587ce18fca4c8300fcf401284a2bcd Reviewed-on: https://go-review.googlesource.com/c/go/+/309930 Trust: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com>
766 lines
16 KiB
ArmAsm
766 lines
16 KiB
ArmAsm
// Copyright 2009 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 AMD64, OpenBSD.
|
|
// System calls are implemented in libc/libpthread, this file
|
|
// contains trampolines that convert from Go to C calling convention.
|
|
// Some direct system call implementations currently remain.
|
|
//
|
|
|
|
#include "go_asm.h"
|
|
#include "go_tls.h"
|
|
#include "textflag.h"
|
|
#include "cgo/abi_amd64.h"
|
|
|
|
#define CLOCK_MONOTONIC $3
|
|
|
|
TEXT runtime·settls(SB),NOSPLIT,$0
|
|
// Nothing to do, pthread already set thread-local storage up.
|
|
RET
|
|
|
|
// 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,$0
|
|
// DI points to the m.
|
|
// We are already on m's g0 stack.
|
|
|
|
// Transition from C ABI to Go ABI.
|
|
PUSH_REGS_HOST_TO_ABI0()
|
|
|
|
// Load g and save to TLS entry.
|
|
// See cmd/link/internal/ld/sym.go:computeTLSOffset.
|
|
MOVQ m_g0(DI), DX // g
|
|
MOVQ DX, -8(FS)
|
|
|
|
CALL runtime·mstart(SB)
|
|
|
|
POP_REGS_HOST_TO_ABI0()
|
|
|
|
// 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).
|
|
XORL AX, AX
|
|
RET
|
|
|
|
TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
|
|
MOVQ fn+0(FP), AX
|
|
MOVL sig+8(FP), DI
|
|
MOVQ info+16(FP), SI
|
|
MOVQ ctx+24(FP), DX
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
ANDQ $~15, SP // alignment for x86_64 ABI
|
|
CALL AX
|
|
MOVQ BP, SP
|
|
POPQ BP
|
|
RET
|
|
|
|
// Called using C ABI.
|
|
TEXT runtime·sigtramp<ABIInternal>(SB),NOSPLIT,$0
|
|
// Transition from C ABI to Go ABI.
|
|
PUSH_REGS_HOST_TO_ABI0()
|
|
|
|
// Call into the Go signal handler
|
|
NOP SP // disable vet stack checking
|
|
ADJSP $24
|
|
MOVQ DI, 0(SP) // sig
|
|
MOVQ SI, 8(SP) // info
|
|
MOVQ DX, 16(SP) // ctx
|
|
CALL ·sigtrampgo(SB)
|
|
ADJSP $-24
|
|
|
|
POP_REGS_HOST_TO_ABI0()
|
|
RET
|
|
|
|
//
|
|
// These trampolines help convert from Go calling convention to C calling convention.
|
|
// They should be called with asmcgocall.
|
|
// A pointer to the arguments is passed in DI.
|
|
// A single int32 result is returned in AX.
|
|
// (For more results, make an args/results structure.)
|
|
TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVQ 0(DI), DI // arg 1 - attr
|
|
CALL libc_pthread_attr_init(SB)
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·pthread_attr_destroy_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVQ 0(DI), DI // arg 1 - attr
|
|
CALL libc_pthread_attr_destroy(SB)
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·pthread_attr_getstacksize_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVQ 8(DI), SI // arg 2 - stacksize
|
|
MOVQ 0(DI), DI // arg 1 - attr
|
|
CALL libc_pthread_attr_getstacksize(SB)
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVQ 8(DI), SI // arg 2 - detachstate
|
|
MOVQ 0(DI), DI // arg 1 - attr
|
|
CALL libc_pthread_attr_setdetachstate(SB)
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
SUBQ $16, SP
|
|
MOVQ 0(DI), SI // arg 2 - attr
|
|
MOVQ 8(DI), DX // arg 3 - start
|
|
MOVQ 16(DI), CX // arg 4 - arg
|
|
MOVQ SP, DI // arg 1 - &thread (discarded)
|
|
CALL libc_pthread_create(SB)
|
|
MOVQ BP, SP
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·thrkill_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVL 8(DI), SI // arg 2 - signal
|
|
MOVQ $0, DX // arg 3 - tcb
|
|
MOVL 0(DI), DI // arg 1 - tid
|
|
CALL libc_thrkill(SB)
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·thrsleep_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVL 8(DI), SI // arg 2 - clock_id
|
|
MOVQ 16(DI), DX // arg 3 - abstime
|
|
MOVQ 24(DI), CX // arg 4 - lock
|
|
MOVQ 32(DI), R8 // arg 5 - abort
|
|
MOVQ 0(DI), DI // arg 1 - id
|
|
CALL libc_thrsleep(SB)
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·thrwakeup_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVL 8(DI), SI // arg 2 - count
|
|
MOVQ 0(DI), DI // arg 1 - id
|
|
CALL libc_thrwakeup(SB)
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·exit_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVL 0(DI), DI // arg 1 exit status
|
|
CALL libc_exit(SB)
|
|
MOVL $0xf1, 0xf1 // crash
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·getthrid_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVQ DI, BX // BX is caller-save
|
|
CALL libc_getthrid(SB)
|
|
MOVL AX, 0(BX) // return value
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVL 0(DI), BX // signal
|
|
CALL libc_getpid(SB)
|
|
MOVL AX, DI // arg 1 pid
|
|
MOVL BX, SI // arg 2 signal
|
|
CALL libc_kill(SB)
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·sched_yield_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
CALL libc_sched_yield(SB)
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP // make a frame; keep stack aligned
|
|
MOVQ SP, BP
|
|
MOVQ DI, BX
|
|
MOVQ 0(BX), DI // arg 1 addr
|
|
MOVQ 8(BX), SI // arg 2 len
|
|
MOVL 16(BX), DX // arg 3 prot
|
|
MOVL 20(BX), CX // arg 4 flags
|
|
MOVL 24(BX), R8 // arg 5 fid
|
|
MOVL 28(BX), R9 // arg 6 offset
|
|
CALL libc_mmap(SB)
|
|
XORL DX, DX
|
|
CMPQ AX, $-1
|
|
JNE ok
|
|
CALL libc_errno(SB)
|
|
MOVLQSX (AX), DX // errno
|
|
XORQ AX, AX
|
|
ok:
|
|
MOVQ AX, 32(BX)
|
|
MOVQ DX, 40(BX)
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVQ 8(DI), SI // arg 2 len
|
|
MOVQ 0(DI), DI // arg 1 addr
|
|
CALL libc_munmap(SB)
|
|
TESTQ AX, AX
|
|
JEQ 2(PC)
|
|
MOVL $0xf1, 0xf1 // crash
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·madvise_trampoline(SB), NOSPLIT, $0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVQ 8(DI), SI // arg 2 len
|
|
MOVL 16(DI), DX // arg 3 advice
|
|
MOVQ 0(DI), DI // arg 1 addr
|
|
CALL libc_madvise(SB)
|
|
// ignore failure - maybe pages are locked
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·open_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVL 8(DI), SI // arg 2 - flags
|
|
MOVL 12(DI), DX // arg 3 - mode
|
|
MOVQ 0(DI), DI // arg 1 - path
|
|
XORL AX, AX // vararg: say "no float args"
|
|
CALL libc_open(SB)
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·close_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVL 0(DI), DI // arg 1 - fd
|
|
CALL libc_close(SB)
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·read_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVQ 8(DI), SI // arg 2 - buf
|
|
MOVL 16(DI), DX // arg 3 - count
|
|
MOVL 0(DI), DI // arg 1 - fd
|
|
CALL libc_read(SB)
|
|
TESTL AX, AX
|
|
JGE noerr
|
|
CALL libc_errno(SB)
|
|
MOVL (AX), AX // errno
|
|
NEGL AX // caller expects negative errno value
|
|
noerr:
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·write_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVQ 8(DI), SI // arg 2 buf
|
|
MOVL 16(DI), DX // arg 3 count
|
|
MOVL 0(DI), DI // arg 1 fd
|
|
CALL libc_write(SB)
|
|
TESTL AX, AX
|
|
JGE noerr
|
|
CALL libc_errno(SB)
|
|
MOVL (AX), AX // errno
|
|
NEGL AX // caller expects negative errno value
|
|
noerr:
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·pipe2_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVL 8(DI), SI // arg 2 flags
|
|
MOVQ 0(DI), DI // arg 1 filedes
|
|
CALL libc_pipe2(SB)
|
|
TESTL AX, AX
|
|
JEQ 3(PC)
|
|
CALL libc_errno(SB)
|
|
MOVL (AX), AX // errno
|
|
NEGL AX // caller expects negative errno value
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVQ 8(DI), SI // arg 2 new
|
|
MOVQ 16(DI), DX // arg 3 old
|
|
MOVL 0(DI), DI // arg 1 which
|
|
CALL libc_setitimer(SB)
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVL 0(DI), DI // arg 1 usec
|
|
CALL libc_usleep(SB)
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVL 8(DI), SI // arg 2 miblen
|
|
MOVQ 16(DI), DX // arg 3 out
|
|
MOVQ 24(DI), CX // arg 4 size
|
|
MOVQ 32(DI), R8 // arg 5 dst
|
|
MOVQ 40(DI), R9 // arg 6 ndst
|
|
MOVQ 0(DI), DI // arg 1 mib
|
|
CALL libc_sysctl(SB)
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
CALL libc_kqueue(SB)
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVQ 8(DI), SI // arg 2 keventt
|
|
MOVL 16(DI), DX // arg 3 nch
|
|
MOVQ 24(DI), CX // arg 4 ev
|
|
MOVL 32(DI), R8 // arg 5 nev
|
|
MOVQ 40(DI), R9 // arg 6 ts
|
|
MOVL 0(DI), DI // arg 1 kq
|
|
CALL libc_kevent(SB)
|
|
CMPL AX, $-1
|
|
JNE ok
|
|
CALL libc_errno(SB)
|
|
MOVL (AX), AX // errno
|
|
NEGL AX // caller expects negative errno value
|
|
ok:
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·clock_gettime_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP // make a frame; keep stack aligned
|
|
MOVQ SP, BP
|
|
MOVQ 8(DI), SI // arg 2 tp
|
|
MOVL 0(DI), DI // arg 1 clock_id
|
|
CALL libc_clock_gettime(SB)
|
|
TESTL AX, AX
|
|
JEQ 2(PC)
|
|
MOVL $0xf1, 0xf1 // crash
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVL 4(DI), SI // arg 2 cmd
|
|
MOVL 8(DI), DX // arg 3 arg
|
|
MOVL 0(DI), DI // arg 1 fd
|
|
XORL AX, AX // vararg: say "no float args"
|
|
CALL libc_fcntl(SB)
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVQ 8(DI), SI // arg 2 new
|
|
MOVQ 16(DI), DX // arg 3 old
|
|
MOVL 0(DI), DI // arg 1 sig
|
|
CALL libc_sigaction(SB)
|
|
TESTL AX, AX
|
|
JEQ 2(PC)
|
|
MOVL $0xf1, 0xf1 // crash
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVQ 8(DI), SI // arg 2 new
|
|
MOVQ 16(DI), DX // arg 3 old
|
|
MOVL 0(DI), DI // arg 1 how
|
|
CALL libc_pthread_sigmask(SB)
|
|
TESTL AX, AX
|
|
JEQ 2(PC)
|
|
MOVL $0xf1, 0xf1 // crash
|
|
POPQ BP
|
|
RET
|
|
|
|
TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
MOVQ 8(DI), SI // arg 2 old
|
|
MOVQ 0(DI), DI // arg 1 new
|
|
CALL libc_sigaltstack(SB)
|
|
TESTQ AX, AX
|
|
JEQ 2(PC)
|
|
MOVL $0xf1, 0xf1 // crash
|
|
POPQ BP
|
|
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).
|
|
//
|
|
// syscall expects a 32-bit result and tests for 32-bit -1
|
|
// to decide there was an error.
|
|
TEXT runtime·syscall(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
SUBQ $16, SP
|
|
MOVQ (0*8)(DI), CX // fn
|
|
MOVQ (2*8)(DI), SI // a2
|
|
MOVQ (3*8)(DI), DX // a3
|
|
MOVQ DI, (SP)
|
|
MOVQ (1*8)(DI), DI // a1
|
|
XORL AX, AX // vararg: say "no float args"
|
|
|
|
CALL CX
|
|
|
|
MOVQ (SP), DI
|
|
MOVQ AX, (4*8)(DI) // r1
|
|
MOVQ DX, (5*8)(DI) // r2
|
|
|
|
// Standard libc functions return -1 on error
|
|
// and set errno.
|
|
CMPL AX, $-1 // Note: high 32 bits are junk
|
|
JNE ok
|
|
|
|
// Get error code from libc.
|
|
CALL libc_errno(SB)
|
|
MOVLQSX (AX), AX
|
|
MOVQ (SP), DI
|
|
MOVQ AX, (6*8)(DI) // err
|
|
|
|
ok:
|
|
XORL AX, AX // no error (it's ignored anyway)
|
|
MOVQ BP, SP
|
|
POPQ BP
|
|
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).
|
|
//
|
|
// syscallX is like syscall but expects a 64-bit result
|
|
// and tests for 64-bit -1 to decide there was an error.
|
|
TEXT runtime·syscallX(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
SUBQ $16, SP
|
|
MOVQ (0*8)(DI), CX // fn
|
|
MOVQ (2*8)(DI), SI // a2
|
|
MOVQ (3*8)(DI), DX // a3
|
|
MOVQ DI, (SP)
|
|
MOVQ (1*8)(DI), DI // a1
|
|
XORL AX, AX // vararg: say "no float args"
|
|
|
|
CALL CX
|
|
|
|
MOVQ (SP), DI
|
|
MOVQ AX, (4*8)(DI) // r1
|
|
MOVQ DX, (5*8)(DI) // r2
|
|
|
|
// Standard libc functions return -1 on error
|
|
// and set errno.
|
|
CMPQ AX, $-1
|
|
JNE ok
|
|
|
|
// Get error code from libc.
|
|
CALL libc_errno(SB)
|
|
MOVLQSX (AX), AX
|
|
MOVQ (SP), DI
|
|
MOVQ AX, (6*8)(DI) // err
|
|
|
|
ok:
|
|
XORL AX, AX // no error (it's ignored anyway)
|
|
MOVQ BP, SP
|
|
POPQ BP
|
|
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).
|
|
//
|
|
// syscall6 expects a 32-bit result and tests for 32-bit -1
|
|
// to decide there was an error.
|
|
TEXT runtime·syscall6(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
SUBQ $16, SP
|
|
MOVQ (0*8)(DI), R11// fn
|
|
MOVQ (2*8)(DI), SI // a2
|
|
MOVQ (3*8)(DI), DX // a3
|
|
MOVQ (4*8)(DI), CX // a4
|
|
MOVQ (5*8)(DI), R8 // a5
|
|
MOVQ (6*8)(DI), R9 // a6
|
|
MOVQ DI, (SP)
|
|
MOVQ (1*8)(DI), DI // a1
|
|
XORL AX, AX // vararg: say "no float args"
|
|
|
|
CALL R11
|
|
|
|
MOVQ (SP), DI
|
|
MOVQ AX, (7*8)(DI) // r1
|
|
MOVQ DX, (8*8)(DI) // r2
|
|
|
|
CMPL AX, $-1
|
|
JNE ok
|
|
|
|
CALL libc_errno(SB)
|
|
MOVLQSX (AX), AX
|
|
MOVQ (SP), DI
|
|
MOVQ AX, (9*8)(DI) // err
|
|
|
|
ok:
|
|
XORL AX, AX // no error (it's ignored anyway)
|
|
MOVQ BP, SP
|
|
POPQ BP
|
|
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).
|
|
//
|
|
// syscall6X is like syscall6 but expects a 64-bit result
|
|
// and tests for 64-bit -1 to decide there was an error.
|
|
TEXT runtime·syscall6X(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
SUBQ $16, SP
|
|
MOVQ (0*8)(DI), R11// fn
|
|
MOVQ (2*8)(DI), SI // a2
|
|
MOVQ (3*8)(DI), DX // a3
|
|
MOVQ (4*8)(DI), CX // a4
|
|
MOVQ (5*8)(DI), R8 // a5
|
|
MOVQ (6*8)(DI), R9 // a6
|
|
MOVQ DI, (SP)
|
|
MOVQ (1*8)(DI), DI // a1
|
|
XORL AX, AX // vararg: say "no float args"
|
|
|
|
CALL R11
|
|
|
|
MOVQ (SP), DI
|
|
MOVQ AX, (7*8)(DI) // r1
|
|
MOVQ DX, (8*8)(DI) // r2
|
|
|
|
CMPQ AX, $-1
|
|
JNE ok
|
|
|
|
CALL libc_errno(SB)
|
|
MOVLQSX (AX), AX
|
|
MOVQ (SP), DI
|
|
MOVQ AX, (9*8)(DI) // err
|
|
|
|
ok:
|
|
XORL AX, AX // no error (it's ignored anyway)
|
|
MOVQ BP, SP
|
|
POPQ BP
|
|
RET
|
|
|
|
// syscall10 calls a function in libc on behalf of the syscall package.
|
|
// syscall10 takes a pointer to a struct like:
|
|
// struct {
|
|
// fn uintptr
|
|
// a1 uintptr
|
|
// a2 uintptr
|
|
// a3 uintptr
|
|
// a4 uintptr
|
|
// a5 uintptr
|
|
// a6 uintptr
|
|
// a7 uintptr
|
|
// a8 uintptr
|
|
// a9 uintptr
|
|
// a10 uintptr
|
|
// r1 uintptr
|
|
// r2 uintptr
|
|
// err uintptr
|
|
// }
|
|
// syscall10 must be called on the g0 stack with the
|
|
// C calling convention (use libcCall).
|
|
TEXT runtime·syscall10(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
SUBQ $48, SP
|
|
|
|
// Arguments a1 to a6 get passed in registers, with a7 onwards being
|
|
// passed via the stack per the x86-64 System V ABI
|
|
// (https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf).
|
|
MOVQ (7*8)(DI), R10 // a7
|
|
MOVQ (8*8)(DI), R11 // a8
|
|
MOVQ (9*8)(DI), R12 // a9
|
|
MOVQ (10*8)(DI), R13 // a10
|
|
MOVQ R10, (0*8)(SP) // a7
|
|
MOVQ R11, (1*8)(SP) // a8
|
|
MOVQ R12, (2*8)(SP) // a9
|
|
MOVQ R13, (3*8)(SP) // a10
|
|
MOVQ (0*8)(DI), R11 // fn
|
|
MOVQ (2*8)(DI), SI // a2
|
|
MOVQ (3*8)(DI), DX // a3
|
|
MOVQ (4*8)(DI), CX // a4
|
|
MOVQ (5*8)(DI), R8 // a5
|
|
MOVQ (6*8)(DI), R9 // a6
|
|
MOVQ DI, (4*8)(SP)
|
|
MOVQ (1*8)(DI), DI // a1
|
|
XORL AX, AX // vararg: say "no float args"
|
|
|
|
CALL R11
|
|
|
|
MOVQ (4*8)(SP), DI
|
|
MOVQ AX, (11*8)(DI) // r1
|
|
MOVQ DX, (12*8)(DI) // r2
|
|
|
|
CMPL AX, $-1
|
|
JNE ok
|
|
|
|
CALL libc_errno(SB)
|
|
MOVLQSX (AX), AX
|
|
MOVQ (4*8)(SP), DI
|
|
MOVQ AX, (13*8)(DI) // err
|
|
|
|
ok:
|
|
XORL AX, AX // no error (it's ignored anyway)
|
|
MOVQ BP, SP
|
|
POPQ BP
|
|
RET
|
|
|
|
// syscall10X calls a function in libc on behalf of the syscall package.
|
|
// syscall10X takes a pointer to a struct like:
|
|
// struct {
|
|
// fn uintptr
|
|
// a1 uintptr
|
|
// a2 uintptr
|
|
// a3 uintptr
|
|
// a4 uintptr
|
|
// a5 uintptr
|
|
// a6 uintptr
|
|
// a7 uintptr
|
|
// a8 uintptr
|
|
// a9 uintptr
|
|
// a10 uintptr
|
|
// r1 uintptr
|
|
// r2 uintptr
|
|
// err uintptr
|
|
// }
|
|
// syscall10X must be called on the g0 stack with the
|
|
// C calling convention (use libcCall).
|
|
//
|
|
// syscall10X is like syscall10 but expects a 64-bit result
|
|
// and tests for 64-bit -1 to decide there was an error.
|
|
TEXT runtime·syscall10X(SB),NOSPLIT,$0
|
|
PUSHQ BP
|
|
MOVQ SP, BP
|
|
SUBQ $48, SP
|
|
|
|
// Arguments a1 to a6 get passed in registers, with a7 onwards being
|
|
// passed via the stack per the x86-64 System V ABI
|
|
// (https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf).
|
|
MOVQ (7*8)(DI), R10 // a7
|
|
MOVQ (8*8)(DI), R11 // a8
|
|
MOVQ (9*8)(DI), R12 // a9
|
|
MOVQ (10*8)(DI), R13 // a10
|
|
MOVQ R10, (0*8)(SP) // a7
|
|
MOVQ R11, (1*8)(SP) // a8
|
|
MOVQ R12, (2*8)(SP) // a9
|
|
MOVQ R13, (3*8)(SP) // a10
|
|
MOVQ (0*8)(DI), R11 // fn
|
|
MOVQ (2*8)(DI), SI // a2
|
|
MOVQ (3*8)(DI), DX // a3
|
|
MOVQ (4*8)(DI), CX // a4
|
|
MOVQ (5*8)(DI), R8 // a5
|
|
MOVQ (6*8)(DI), R9 // a6
|
|
MOVQ DI, (4*8)(SP)
|
|
MOVQ (1*8)(DI), DI // a1
|
|
XORL AX, AX // vararg: say "no float args"
|
|
|
|
CALL R11
|
|
|
|
MOVQ (4*8)(SP), DI
|
|
MOVQ AX, (11*8)(DI) // r1
|
|
MOVQ DX, (12*8)(DI) // r2
|
|
|
|
CMPQ AX, $-1
|
|
JNE ok
|
|
|
|
CALL libc_errno(SB)
|
|
MOVLQSX (AX), AX
|
|
MOVQ (4*8)(SP), DI
|
|
MOVQ AX, (13*8)(DI) // err
|
|
|
|
ok:
|
|
XORL AX, AX // no error (it's ignored anyway)
|
|
MOVQ BP, SP
|
|
POPQ BP
|
|
RET
|