]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: deduplicate syscall assembly for darwin
authorqmuntal <quimmuntal@gmail.com>
Tue, 26 Aug 2025 09:47:51 +0000 (11:47 +0200)
committerQuim Muntal <quimmuntal@gmail.com>
Mon, 15 Sep 2025 08:16:22 +0000 (01:16 -0700)
The darwin port provides different syscall functions that only
differ on how they handle the errors, and they are all written
in assembly.

This duplication can be removed by factoring out the error handling
logic to arch-agnostic Go code and leaving the assembly functions
with the only reponsibility of making the syscall and mapping
parameters between ABIs.

Updates #51087

Cq-Include-Trybots: luci.golang.try:gotip-darwin-arm64-longtest,gotip-darwin-amd64-longtest
Change-Id: I9524377f3ef9c9a638412c7e87c8f46a33ee3453
Reviewed-on: https://go-review.googlesource.com/c/go/+/699135
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/runtime/sys_darwin.go
src/runtime/sys_darwin_amd64.s
src/runtime/sys_darwin_arm64.s

index ad423afc60d7417491978beffb934a934f7f1adc..aa628021a05a393ee187e1c46d64079b68446bf0 100644 (file)
@@ -10,12 +10,27 @@ import (
        "unsafe"
 )
 
+//go:nosplit
+func libcError() uintptr {
+       errPtr, _ := syscall(abi.FuncPCABI0(libc_error_trampoline), 0, 0, 0)
+       return errPtr
+}
+func libc_error_trampoline()
+
 // The X versions of syscall expect the libc call to return a 64-bit result.
 // Otherwise (the non-X version) expects a 32-bit result.
 // This distinction is required because an error is indicated by returning -1,
 // and we need to know whether to check 32 or 64 bits of the result.
 // (Some libc functions that return 32 bits put junk in the upper 32 bits of AX.)
 
+//go:nosplit
+func syscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr) {
+       args := struct{ fn, a1, a2, a3, r1, r2 uintptr }{fn, a1, a2, a3, r1, r2}
+       libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall_trampoline)), unsafe.Pointer(&args))
+       return args.r1, args.r2
+}
+func syscall_trampoline()
+
 // golang.org/x/sys linknames syscall_syscall
 // (in addition to standard package syscall).
 // Do not remove or change the type signature.
@@ -23,24 +38,28 @@ import (
 //go:linkname syscall_syscall syscall.syscall
 //go:nosplit
 func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
-       args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
        entersyscall()
-       libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&args))
+       r1, r2, err = syscall_rawSyscall(fn, a1, a2, a3)
        exitsyscall()
-       return args.r1, args.r2, args.err
+       return r1, r2, err
 }
-func syscall()
 
 //go:linkname syscall_syscallX syscall.syscallX
 //go:nosplit
 func syscall_syscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
-       args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
        entersyscall()
-       libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallX)), unsafe.Pointer(&args))
+       r1, r2, err = syscall_rawSyscallX(fn, a1, a2, a3)
        exitsyscall()
-       return args.r1, args.r2, args.err
+       return r1, r2, err
 }
-func syscallX()
+
+//go:nosplit
+func syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr) {
+       args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2 uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2}
+       libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6_trampoline)), unsafe.Pointer(&args))
+       return args.r1, args.r2
+}
+func syscall6_trampoline()
 
 // golang.org/x/sys linknames syscall.syscall6
 // (in addition to standard package syscall).
@@ -56,13 +75,28 @@ func syscallX()
 //go:linkname syscall_syscall6 syscall.syscall6
 //go:nosplit
 func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
-       args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2, err}
        entersyscall()
-       libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&args))
+       r1, r2, err = syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6)
+       exitsyscall()
+       return r1, r2, err
+}
+
+//go:linkname syscall_syscall6X syscall.syscall6X
+//go:nosplit
+func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+       entersyscall()
+       r1, r2, err = syscall_rawSyscall6X(fn, a1, a2, a3, a4, a5, a6)
        exitsyscall()
-       return args.r1, args.r2, args.err
+       return r1, r2, err
 }
-func syscall6()
+
+//go:nosplit
+func syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr) {
+       args := struct{ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2 uintptr }{fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2}
+       libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall9_trampoline)), unsafe.Pointer(&args))
+       return args.r1, args.r2
+}
+func syscall9_trampoline()
 
 // golang.org/x/sys linknames syscall.syscall9
 // (in addition to standard package syscall).
@@ -71,24 +105,11 @@ func syscall6()
 //go:linkname syscall_syscall9 syscall.syscall9
 //go:nosplit
 func syscall_syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
-       args := struct{ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err}
-       entersyscall()
-       libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall9)), unsafe.Pointer(&args))
-       exitsyscall()
-       return args.r1, args.r2, args.err
-}
-func syscall9()
-
-//go:linkname syscall_syscall6X syscall.syscall6X
-//go:nosplit
-func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
-       args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2, err}
        entersyscall()
-       libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6X)), unsafe.Pointer(&args))
+       r1, r2, err = syscall_rawSyscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9)
        exitsyscall()
-       return args.r1, args.r2, args.err
+       return r1, r2, err
 }
-func syscall6X()
 
 // golang.org/x/sys linknames syscall.syscallPtr
 // (in addition to standard package syscall).
@@ -97,13 +118,11 @@ func syscall6X()
 //go:linkname syscall_syscallPtr syscall.syscallPtr
 //go:nosplit
 func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
-       args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
        entersyscall()
-       libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallPtr)), unsafe.Pointer(&args))
+       r1, r2, err = syscall_rawSyscallPtr(fn, a1, a2, a3)
        exitsyscall()
-       return args.r1, args.r2, args.err
+       return r1, r2, err
 }
-func syscallPtr()
 
 // golang.org/x/sys linknames syscall_rawSyscall
 // (in addition to standard package syscall).
@@ -112,9 +131,30 @@ func syscallPtr()
 //go:linkname syscall_rawSyscall syscall.rawSyscall
 //go:nosplit
 func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
-       args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
-       libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&args))
-       return args.r1, args.r2, args.err
+       r1, r2 = syscall(fn, a1, a2, a3)
+       // Check if r1 low 32 bits is -1, indicating an error.
+       if int32(r1) == -1 {
+               err = libcError()
+       }
+       return r1, r2, err
+}
+
+//go:nosplit
+func syscall_rawSyscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+       r1, r2 = syscall(fn, a1, a2, a3)
+       if r1 == ^uintptr(0) {
+               err = libcError()
+       }
+       return r1, r2, err
+}
+
+//go:nosplit
+func syscall_rawSyscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+       r1, r2 = syscall(fn, a1, a2, a3)
+       if r1 == 0 {
+               err = libcError()
+       }
+       return r1, r2, err
 }
 
 // golang.org/x/sys linknames syscall_rawSyscall6
@@ -124,9 +164,31 @@ func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
 //go:linkname syscall_rawSyscall6 syscall.rawSyscall6
 //go:nosplit
 func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
-       args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2, err}
-       libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&args))
-       return args.r1, args.r2, args.err
+       r1, r2 = syscall6(fn, a1, a2, a3, a4, a5, a6)
+       // Check if r1 low 32 bits is -1, indicating an error.
+       if int32(r1) == -1 {
+               err = libcError()
+       }
+       return r1, r2, err
+}
+
+//go:nosplit
+func syscall_rawSyscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+       r1, r2 = syscall6(fn, a1, a2, a3, a4, a5, a6)
+       if r1 == ^uintptr(0) {
+               err = libcError()
+       }
+       return r1, r2, err
+}
+
+//go:nosplit
+func syscall_rawSyscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
+       r1, r2 = syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+       // Check if r1 low 32 bits is -1, indicating an error.
+       if int32(r1) == -1 {
+               err = libcError()
+       }
+       return r1, r2, err
 }
 
 // crypto_x509_syscall is used in crypto/x509/internal/macos to call into Security.framework and CF.
index cc4e52d305ab5908e57172a6ecd7143b202c7acd..e7462579677d232d993086a3e72d29c556400eae 100644 (file)
@@ -506,8 +506,8 @@ TEXT runtime·arc4random_buf_trampoline(SB),NOSPLIT,$0
        CALL    libc_arc4random_buf(SB)
        RET
 
-// syscall calls a function in libc on behalf of the syscall package.
-// syscall takes a pointer to a struct like:
+// syscall_trampoline calls a function in libc on behalf of the syscall package.
+// syscall_trampoline takes a pointer to a struct like:
 // struct {
 //     fn    uintptr
 //     a1    uintptr
@@ -515,14 +515,10 @@ TEXT runtime·arc4random_buf_trampoline(SB),NOSPLIT,$0
 //     a3    uintptr
 //     r1    uintptr
 //     r2    uintptr
-//     err   uintptr
 // }
-// syscall must be called on the g0 stack with the
+// syscall_trampoline 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,$16
+TEXT runtime·syscall_trampoline(SB),NOSPLIT,$16
        MOVQ    (0*8)(DI), CX // fn
        MOVQ    (2*8)(DI), SI // a2
        MOVQ    (3*8)(DI), DX // a3
@@ -536,99 +532,11 @@ TEXT runtime·syscall(SB),NOSPLIT,$16
        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_error(SB)
-       MOVLQSX (AX), AX
-       MOVQ    (SP), DI
-       MOVQ    AX, (6*8)(DI) // err
-
-ok:
        XORL    AX, AX        // no error (it's ignored anyway)
        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,$16
-       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_error(SB)
-       MOVLQSX (AX), AX
-       MOVQ    (SP), DI
-       MOVQ    AX, (6*8)(DI) // err
-
-ok:
-       XORL    AX, AX        // no error (it's ignored anyway)
-       RET
-
-// syscallPtr is like syscallX except that the libc function reports an
-// error by returning NULL and setting errno.
-TEXT runtime·syscallPtr(SB),NOSPLIT,$16
-       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
-
-       // syscallPtr libc functions return NULL on error
-       // and set errno.
-       TESTQ   AX, AX
-       JNE     ok
-
-       // Get error code from libc.
-       CALL    libc_error(SB)
-       MOVLQSX (AX), AX
-       MOVQ    (SP), DI
-       MOVQ    AX, (6*8)(DI) // err
-
-ok:
-       XORL    AX, AX        // no error (it's ignored anyway)
-       RET
-
-// syscall6 calls a function in libc on behalf of the syscall package.
-// syscall6 takes a pointer to a struct like:
+// syscall6_trampoline calls a function in libc on behalf of the syscall package.
+// syscall6_trampoline takes a pointer to a struct like:
 // struct {
 //     fn    uintptr
 //     a1    uintptr
@@ -639,14 +547,10 @@ ok:
 //     a6    uintptr
 //     r1    uintptr
 //     r2    uintptr
-//     err   uintptr
 // }
-// syscall6 must be called on the g0 stack with the
+// syscall6_trampoline 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,$16
+TEXT runtime·syscall6_trampoline(SB),NOSPLIT,$16
        MOVQ    (0*8)(DI), R11// fn
        MOVQ    (2*8)(DI), SI // a2
        MOVQ    (3*8)(DI), DX // a3
@@ -663,68 +567,11 @@ TEXT runtime·syscall6(SB),NOSPLIT,$16
        MOVQ    AX, (7*8)(DI) // r1
        MOVQ    DX, (8*8)(DI) // r2
 
-       CMPL    AX, $-1
-       JNE     ok
-
-       CALL    libc_error(SB)
-       MOVLQSX (AX), AX
-       MOVQ    (SP), DI
-       MOVQ    AX, (9*8)(DI) // err
-
-ok:
        XORL    AX, AX        // no error (it's ignored anyway)
        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,$16
-       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_error(SB)
-       MOVLQSX (AX), AX
-       MOVQ    (SP), DI
-       MOVQ    AX, (9*8)(DI) // err
-
-ok:
-       XORL    AX, AX        // no error (it's ignored anyway)
-       RET
-
-// syscall9 calls a function in libc on behalf of the syscall package.
-// syscall9 takes a pointer to a struct like:
+// syscall9_trampoline calls a function in libc on behalf of the syscall package.
+// syscall9_trampoline takes a pointer to a struct like:
 // struct {
 //     fn    uintptr
 //     a1    uintptr
@@ -740,12 +587,9 @@ ok:
 //     r2    uintptr
 //     err   uintptr
 // }
-// syscall9 must be called on the g0 stack with the
+// syscall9_trampoline must be called on the g0 stack with the
 // C calling convention (use libcCall).
-//
-// syscall9 expects a 32-bit result and tests for 32-bit -1
-// to decide there was an error.
-TEXT runtime·syscall9(SB),NOSPLIT,$32
+TEXT runtime·syscall9_trampoline(SB),NOSPLIT,$32
        MOVQ    (0*8)(DI), R13// fn
        MOVQ    (2*8)(DI), SI // a2
        MOVQ    (3*8)(DI), DX // a3
@@ -768,16 +612,12 @@ TEXT runtime·syscall9(SB),NOSPLIT,$32
        MOVQ    AX, (10*8)(DI) // r1
        MOVQ    DX, (11*8)(DI) // r2
 
-       CMPL    AX, $-1
-       JNE     ok
+       XORL    AX, AX        // no error (it's ignored anyway)
+       RET
 
+TEXT runtime·libc_error_trampoline(SB),NOSPLIT,$0
        CALL    libc_error(SB)
        MOVLQSX (AX), AX
-       MOVQ    24(SP), DI
-       MOVQ    AX, (12*8)(DI) // err
-
-ok:
-       XORL    AX, AX        // no error (it's ignored anyway)
        RET
 
 // syscall_x509 is for crypto/x509. It is like syscall6 but does not check for errors,
index a3901bdb3bfbb82648405970f92a9ff2bb186406..adbb2adafe94f2ff17b8704642149c5e5b21dccf 100644 (file)
@@ -481,8 +481,8 @@ TEXT runtime·arc4random_buf_trampoline(SB),NOSPLIT,$0
        BL      libc_arc4random_buf(SB)
        RET
 
-// syscall calls a function in libc on behalf of the syscall package.
-// syscall takes a pointer to a struct like:
+// syscall_trampoline calls a function in libc on behalf of the syscall package.
+// syscall_trampoline takes a pointer to a struct like:
 // struct {
 //     fn    uintptr
 //     a1    uintptr
@@ -490,12 +490,11 @@ TEXT runtime·arc4random_buf_trampoline(SB),NOSPLIT,$0
 //     a3    uintptr
 //     r1    uintptr
 //     r2    uintptr
-//     err   uintptr
 // }
-// syscall must be called on the g0 stack with the
+// syscall_trampoline 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
+TEXT runtime·syscall_trampoline(SB),NOSPLIT,$0
+       SUB     $16, RSP // push structure pointer
        MOVD    R0, 8(RSP)
 
        MOVD    0(R0), R12      // fn
@@ -517,87 +516,10 @@ TEXT runtime·syscall(SB),NOSPLIT,$0
        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:
+// syscall6_trampoline calls a function in libc on behalf of the syscall package.
+// syscall6_trampoline takes a pointer to a struct like:
 // struct {
 //     fn    uintptr
 //     a1    uintptr
@@ -608,11 +530,10 @@ ok:
 //     a6    uintptr
 //     r1    uintptr
 //     r2    uintptr
-//     err   uintptr
 // }
-// syscall6 must be called on the g0 stack with the
+// syscall6_trampoline must be called on the g0 stack with the
 // C calling convention (use libcCall).
-TEXT runtime·syscall6(SB),NOSPLIT,$0
+TEXT runtime·syscall6_trampoline(SB),NOSPLIT,$0
        SUB     $16, RSP        // push structure pointer
        MOVD    R0, 8(RSP)
 
@@ -625,7 +546,7 @@ TEXT runtime·syscall6(SB),NOSPLIT,$0
        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
+       // See syscall_trampoline above. The only function this applies to is openat, for which the 4th
        // arg must be on the stack.
        MOVD    R3, (RSP)
 
@@ -635,65 +556,10 @@ TEXT runtime·syscall6(SB),NOSPLIT,$0
        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
 
-// syscall9 calls a function in libc on behalf of the syscall package.
-// syscall9 takes a pointer to a struct like:
+// syscall9_trampoline calls a function in libc on behalf of the syscall package.
+// syscall9_trampoline takes a pointer to a struct like:
 // struct {
 //     fn    uintptr
 //     a1    uintptr
@@ -707,11 +573,10 @@ ok:
 //     a9    uintptr
 //     r1    uintptr
 //     r2    uintptr
-//     err   uintptr
 // }
-// syscall9 must be called on the g0 stack with the
+// syscall9_trampoline must be called on the g0 stack with the
 // C calling convention (use libcCall).
-TEXT runtime·syscall9(SB),NOSPLIT,$0
+TEXT runtime·syscall9_trampoline(SB),NOSPLIT,$0
        SUB     $16, RSP        // push structure pointer
        MOVD    R0, 8(RSP)
 
@@ -733,16 +598,11 @@ TEXT runtime·syscall9(SB),NOSPLIT,$0
        ADD     $16, RSP
        MOVD    R0, 80(R2)      // save r1
        MOVD    R1, 88(R2)      // save r2
-       CMPW    $-1, R0
-       BNE     ok
-       SUB     $16, RSP        // push structure pointer
-       MOVD    R2, 8(RSP)
+       RET
+
+TEXT runtime·libc_error_trampoline(SB),NOSPLIT,$0
        BL      libc_error(SB)
        MOVW    (R0), R0
-       MOVD    8(RSP), R2      // pop structure pointer
-       ADD     $16, RSP
-       MOVD    R0, 96(R2)      // save err
-ok:
        RET
 
 // syscall_x509 is for crypto/x509. It is like syscall6 but does not check for errors,