1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3
4//go:build darwin || freebsd || linux || netbsd || windows
5
6#include "textflag.h"
7#include "go_asm.h"
8#include "funcdata.h"
9
10#define STACK_SIZE 208
11#define PTR_ADDRESS (STACK_SIZE - 8)
12
13// syscallX calls a function in libc on behalf of the syscall package.
14// syscallX takes a pointer to a struct like:
15// struct {
16// fn uintptr
17// a1 uintptr
18// a2 uintptr
19// a3 uintptr
20// a4 uintptr
21// a5 uintptr
22// a6 uintptr
23// a7 uintptr
24// a8 uintptr
25// a9 uintptr
26// a10 uintptr
27// a11 uintptr
28// a12 uintptr
29// a13 uintptr
30// a14 uintptr
31// a15 uintptr
32// r1 uintptr
33// r2 uintptr
34// err uintptr
35// }
36// syscallX must be called on the g0 stack with the
37// C calling convention (use libcCall).
38GLOBL ·syscallXABI0(SB), NOPTR|RODATA, $8
39DATA ·syscallXABI0(SB)/8, $syscallX(SB)
40TEXT syscallX(SB), NOSPLIT, $0
41 SUB $STACK_SIZE, RSP // push structure pointer
42 MOVD R0, PTR_ADDRESS(RSP)
43 MOVD R0, R9
44
45 FMOVD syscallArgs_f1(R9), F0 // f1
46 FMOVD syscallArgs_f2(R9), F1 // f2
47 FMOVD syscallArgs_f3(R9), F2 // f3
48 FMOVD syscallArgs_f4(R9), F3 // f4
49 FMOVD syscallArgs_f5(R9), F4 // f5
50 FMOVD syscallArgs_f6(R9), F5 // f6
51 FMOVD syscallArgs_f7(R9), F6 // f7
52 FMOVD syscallArgs_f8(R9), F7 // f8
53
54 MOVD syscallArgs_a1(R9), R0 // a1
55 MOVD syscallArgs_a2(R9), R1 // a2
56 MOVD syscallArgs_a3(R9), R2 // a3
57 MOVD syscallArgs_a4(R9), R3 // a4
58 MOVD syscallArgs_a5(R9), R4 // a5
59 MOVD syscallArgs_a6(R9), R5 // a6
60 MOVD syscallArgs_a7(R9), R6 // a7
61 MOVD syscallArgs_a8(R9), R7 // a8
62 MOVD syscallArgs_arm64_r8(R9), R8 // r8
63
64 MOVD syscallArgs_a9(R9), R10
65 MOVD R10, 0(RSP) // push a9 onto stack
66 MOVD syscallArgs_a10(R9), R10
67 MOVD R10, 8(RSP) // push a10 onto stack
68 MOVD syscallArgs_a11(R9), R10
69 MOVD R10, 16(RSP) // push a11 onto stack
70 MOVD syscallArgs_a12(R9), R10
71 MOVD R10, 24(RSP) // push a12 onto stack
72 MOVD syscallArgs_a13(R9), R10
73 MOVD R10, 32(RSP) // push a13 onto stack
74 MOVD syscallArgs_a14(R9), R10
75 MOVD R10, 40(RSP) // push a14 onto stack
76 MOVD syscallArgs_a15(R9), R10
77 MOVD R10, 48(RSP) // push a15 onto stack
78 MOVD syscallArgs_a16(R9), R10
79 MOVD R10, 56(RSP) // push a16 onto stack
80 MOVD syscallArgs_a17(R9), R10
81 MOVD R10, 64(RSP) // push a17 onto stack
82 MOVD syscallArgs_a18(R9), R10
83 MOVD R10, 72(RSP) // push a18 onto stack
84 MOVD syscallArgs_a19(R9), R10
85 MOVD R10, 80(RSP) // push a19 onto stack
86 MOVD syscallArgs_a20(R9), R10
87 MOVD R10, 88(RSP) // push a20 onto stack
88 MOVD syscallArgs_a21(R9), R10
89 MOVD R10, 96(RSP) // push a21 onto stack
90 MOVD syscallArgs_a22(R9), R10
91 MOVD R10, 104(RSP) // push a22 onto stack
92 MOVD syscallArgs_a23(R9), R10
93 MOVD R10, 112(RSP) // push a23 onto stack
94 MOVD syscallArgs_a24(R9), R10
95 MOVD R10, 120(RSP) // push a24 onto stack
96 MOVD syscallArgs_a25(R9), R10
97 MOVD R10, 128(RSP) // push a25 onto stack
98 MOVD syscallArgs_a26(R9), R10
99 MOVD R10, 136(RSP) // push a26 onto stack
100 MOVD syscallArgs_a27(R9), R10
101 MOVD R10, 144(RSP) // push a27 onto stack
102 MOVD syscallArgs_a28(R9), R10
103 MOVD R10, 152(RSP) // push a28 onto stack
104 MOVD syscallArgs_a29(R9), R10
105 MOVD R10, 160(RSP) // push a29 onto stack
106 MOVD syscallArgs_a30(R9), R10
107 MOVD R10, 168(RSP) // push a30 onto stack
108 MOVD syscallArgs_a31(R9), R10
109 MOVD R10, 176(RSP) // push a31 onto stack
110 MOVD syscallArgs_a32(R9), R10
111 MOVD R10, 184(RSP) // push a32 onto stack
112
113 MOVD syscallArgs_fn(R9), R10 // fn
114 BL (R10)
115
116 MOVD PTR_ADDRESS(RSP), R2 // pop structure pointer
117 ADD $STACK_SIZE, RSP
118
119 MOVD R0, syscallArgs_a1(R2) // save r1
120 MOVD R1, syscallArgs_a2(R2) // save r3
121 FMOVD F0, syscallArgs_f1(R2) // save f0
122 FMOVD F1, syscallArgs_f2(R2) // save f1
123 FMOVD F2, syscallArgs_f3(R2) // save f2
124 FMOVD F3, syscallArgs_f4(R2) // save f3
125
126#ifdef GOOS_darwin
127 BL purego_error(SB)
128 MOVD (R0), R0
129 MOVD R0, syscallArgs_a3(R2) // save errno
130#else
131 MOVD $0, syscallArgs_a3(R2) // no errno here: clear the input argument
132#endif
133 RET