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