1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
//go:build darwin || freebsd || linux || netbsd
#include "textflag.h"
#include "abi_amd64.h"
#include "go_asm.h"
#include "funcdata.h"
#define STACK_SIZE 80
#define PTR_ADDRESS (STACK_SIZE - 8)
// syscall15X calls a function in libc on behalf of the syscall package.
// syscall15X 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
// a11 uintptr
// a12 uintptr
// a13 uintptr
// a14 uintptr
// a15 uintptr
// r1 uintptr
// r2 uintptr
// err uintptr
// }
// syscall15X must be called on the g0 stack with the
// C calling convention (use libcCall).
GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8
DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)
TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0
PUSHQ BP
MOVQ SP, BP
SUBQ $STACK_SIZE, SP
MOVQ DI, PTR_ADDRESS(BP) // save the pointer
MOVQ DI, R11
MOVQ syscall15Args_f1(R11), X0 // f1
MOVQ syscall15Args_f2(R11), X1 // f2
MOVQ syscall15Args_f3(R11), X2 // f3
MOVQ syscall15Args_f4(R11), X3 // f4
MOVQ syscall15Args_f5(R11), X4 // f5
MOVQ syscall15Args_f6(R11), X5 // f6
MOVQ syscall15Args_f7(R11), X6 // f7
MOVQ syscall15Args_f8(R11), X7 // f8
MOVQ syscall15Args_a1(R11), DI // a1
MOVQ syscall15Args_a2(R11), SI // a2
MOVQ syscall15Args_a3(R11), DX // a3
MOVQ syscall15Args_a4(R11), CX // a4
MOVQ syscall15Args_a5(R11), R8 // a5
MOVQ syscall15Args_a6(R11), R9 // a6
// push the remaining paramters onto the stack
MOVQ syscall15Args_a7(R11), R12
MOVQ R12, 0(SP) // push a7
MOVQ syscall15Args_a8(R11), R12
MOVQ R12, 8(SP) // push a8
MOVQ syscall15Args_a9(R11), R12
MOVQ R12, 16(SP) // push a9
MOVQ syscall15Args_a10(R11), R12
MOVQ R12, 24(SP) // push a10
MOVQ syscall15Args_a11(R11), R12
MOVQ R12, 32(SP) // push a11
MOVQ syscall15Args_a12(R11), R12
MOVQ R12, 40(SP) // push a12
MOVQ syscall15Args_a13(R11), R12
MOVQ R12, 48(SP) // push a13
MOVQ syscall15Args_a14(R11), R12
MOVQ R12, 56(SP) // push a14
MOVQ syscall15Args_a15(R11), R12
MOVQ R12, 64(SP) // push a15
XORL AX, AX // vararg: say "no float args"
MOVQ syscall15Args_fn(R11), R10 // fn
CALL R10
MOVQ PTR_ADDRESS(BP), DI // get the pointer back
MOVQ AX, syscall15Args_a1(DI) // r1
MOVQ DX, syscall15Args_a2(DI) // r3
MOVQ X0, syscall15Args_f1(DI) // f1
MOVQ X1, syscall15Args_f2(DI) // f2
XORL AX, AX // no error (it's ignored anyway)
ADDQ $STACK_SIZE, SP
MOVQ BP, SP
POPQ BP
RET
TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0
MOVQ 0(SP), AX // save the return address to calculate the cb index
MOVQ 8(SP), R10 // get the return SP so that we can align register args with stack args
ADDQ $8, SP // remove return address from stack, we are not returning to callbackasm, but to its caller.
// make space for first six int and 8 float arguments below the frame
ADJSP $14*8, SP
MOVSD X0, (1*8)(SP)
MOVSD X1, (2*8)(SP)
MOVSD X2, (3*8)(SP)
MOVSD X3, (4*8)(SP)
MOVSD X4, (5*8)(SP)
MOVSD X5, (6*8)(SP)
MOVSD X6, (7*8)(SP)
MOVSD X7, (8*8)(SP)
MOVQ DI, (9*8)(SP)
MOVQ SI, (10*8)(SP)
MOVQ DX, (11*8)(SP)
MOVQ CX, (12*8)(SP)
MOVQ R8, (13*8)(SP)
MOVQ R9, (14*8)(SP)
LEAQ 8(SP), R8 // R8 = address of args vector
PUSHQ R10 // push the stack pointer below registers
// Switch from the host ABI to the Go ABI.
PUSH_REGS_HOST_TO_ABI0()
// determine index into runtime·cbs table
MOVQ $callbackasm(SB), DX
SUBQ DX, AX
MOVQ $0, DX
MOVQ $5, CX // divide by 5 because each call instruction in ·callbacks is 5 bytes long
DIVL CX
SUBQ $1, AX // subtract 1 because return PC is to the next slot
// Create a struct callbackArgs on our stack to be passed as
// the "frame" to cgocallback and on to callbackWrap.
// $24 to make enough room for the arguments to runtime.cgocallback
SUBQ $(24+callbackArgs__size), SP
MOVQ AX, (24+callbackArgs_index)(SP) // callback index
MOVQ R8, (24+callbackArgs_args)(SP) // address of args vector
MOVQ $0, (24+callbackArgs_result)(SP) // result
LEAQ 24(SP), AX // take the address of callbackArgs
// Call cgocallback, which will call callbackWrap(frame).
MOVQ ·callbackWrap_call(SB), DI // Get the ABIInternal function pointer
MOVQ (DI), DI // without <ABIInternal> by using a closure.
MOVQ AX, SI // frame (address of callbackArgs)
MOVQ $0, CX // context
CALL crosscall2(SB) // runtime.cgocallback(fn, frame, ctxt uintptr)
// Get callback result.
MOVQ (24+callbackArgs_result)(SP), AX
ADDQ $(24+callbackArgs__size), SP // remove callbackArgs struct
POP_REGS_HOST_TO_ABI0()
POPQ R10 // get the SP back
ADJSP $-14*8, SP // remove arguments
MOVQ R10, 0(SP)
RET
|