1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3
4#include "textflag.h"
5#include "go_asm.h"
6#include "funcdata.h"
7#include "internal/abi/abi_arm64.h"
8
9// syscall9X calls a function in libc on behalf of the syscall package.
10// syscall9X takes a pointer to a struct like:
11// struct {
12// fn uintptr
13// a1 uintptr
14// a2 uintptr
15// a3 uintptr
16// a4 uintptr
17// a5 uintptr
18// a6 uintptr
19// a7 uintptr
20// a8 uintptr
21// a9 uintptr
22// r1 uintptr
23// r2 uintptr
24// err uintptr
25// }
26// syscall9X must be called on the g0 stack with the
27// C calling convention (use libcCall).
28GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8
29DATA ·syscall9XABI0(SB)/8, $syscall9X(SB)
30TEXT syscall9X(SB), NOSPLIT, $0
31 SUB $16, RSP // push structure pointer
32 MOVD R0, 8(RSP)
33
34 FMOVD syscall9Args_f1(R0), F0 // f1
35 FMOVD syscall9Args_f2(R0), F1 // f2
36 FMOVD syscall9Args_f3(R0), F2 // f3
37 FMOVD syscall9Args_f4(R0), F3 // f4
38 FMOVD syscall9Args_f5(R0), F4 // f5
39 FMOVD syscall9Args_f6(R0), F5 // f6
40 FMOVD syscall9Args_f7(R0), F6 // f7
41 FMOVD syscall9Args_f8(R0), F7 // f8
42
43 MOVD syscall9Args_fn(R0), R12 // fn
44 MOVD syscall9Args_a2(R0), R1 // a2
45 MOVD syscall9Args_a3(R0), R2 // a3
46 MOVD syscall9Args_a4(R0), R3 // a4
47 MOVD syscall9Args_a5(R0), R4 // a5
48 MOVD syscall9Args_a6(R0), R5 // a6
49 MOVD syscall9Args_a7(R0), R6 // a7
50 MOVD syscall9Args_a8(R0), R7 // a8
51 MOVD syscall9Args_a9(R0), R8 // a9
52 MOVD syscall9Args_a1(R0), R0 // a1
53
54 MOVD R8, (RSP) // push a9 onto stack
55
56 BL (R12)
57
58 MOVD 8(RSP), R2 // pop structure pointer
59 ADD $16, RSP
60 MOVD R0, syscall9Args_r1(R2) // save r1
61 FMOVD F0, syscall9Args_r2(R2) // save r2
62 RET
63
64TEXT callbackasm1(SB), NOSPLIT, $208-0
65 NO_LOCAL_POINTERS
66
67 // On entry, the trampoline in zcallback_darwin_arm64.s left
68 // the callback index in R12 (which is volatile in the C ABI).
69
70 // Save callback register arguments R0-R7.
71 // We do this at the top of the frame so they're contiguous with stack arguments.
72 // The 7*8 setting up R14 looks like a bug but is not: the eighth word
73 // is the space the assembler reserved for our caller's frame pointer,
74 // but we are not called from Go so that space is ours to use,
75 // and we must to be contiguous with the stack arguments.
76 MOVD $arg0-(7*8)(SP), R14
77 STP (R0, R1), (0*8)(R14)
78 STP (R2, R3), (2*8)(R14)
79 STP (R4, R5), (4*8)(R14)
80 STP (R6, R7), (6*8)(R14)
81
82 // Create a struct callbackArgs on our stack.
83 MOVD $cbargs-(18*8+callbackArgs__size)(SP), R13
84 MOVD R12, callbackArgs_index(R13) // callback index
85 MOVD R14, R0
86 MOVD R0, callbackArgs_args(R13) // address of args vector
87 MOVD $0, R0
88 MOVD R0, callbackArgs_result(R13) // result
89
90 // Move parameters into registers
91 // Get the ABIInternal function pointer
92 // without <ABIInternal> by using a closure.
93 MOVD ·callbackWrap_call(SB), R0
94 MOVD (R0), R0 // fn unsafe.Pointer
95 MOVD R13, R1 // frame (&callbackArgs{...})
96 MOVD $0, R3 // ctxt uintptr
97
98 BL crosscall2(SB)
99
100 // Get callback result.
101 MOVD $cbargs-(18*8+callbackArgs__size)(SP), R13
102 MOVD callbackArgs_result(R13), R0
103
104 RET