sys_unix_386.s raw
1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2026 The Ebitengine Authors
3
4 //go:build linux
5
6 #include "textflag.h"
7 #include "go_asm.h"
8 #include "funcdata.h"
9
10 // callbackasm1 is the second part of the callback trampoline.
11 // On entry:
12 // - CX contains the callback index (set by callbackasm)
13 // - 0(SP) contains the return address to C caller
14 // - 4(SP), 8(SP), ... contain C arguments (cdecl convention)
15 //
16 // i386 cdecl calling convention:
17 // - All arguments passed on stack
18 // - Return value in EAX (and EDX for 64-bit)
19 // - Caller cleans the stack
20 // - Callee must preserve: EBX, ESI, EDI, EBP
21 TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0
22 NO_LOCAL_POINTERS
23
24 // Save the return address
25 MOVL 0(SP), AX
26
27 // Allocate stack frame (must be done carefully to preserve args access)
28 // Layout:
29 // 0-15: saved callee-saved registers (BX, SI, DI, BP)
30 // 16-19: saved callback index
31 // 20-23: saved return address
32 // 24-35: callbackArgs struct (12 bytes)
33 // 36-291: copy of C arguments (256 bytes for 64 args, matching callbackMaxFrame)
34 // Total: 292 bytes, round up to 304 for alignment
35 SUBL $304, SP
36
37 // Save callee-saved registers
38 MOVL BX, 0(SP)
39 MOVL SI, 4(SP)
40 MOVL DI, 8(SP)
41 MOVL BP, 12(SP)
42
43 // Save callback index and return address
44 MOVL CX, 16(SP)
45 MOVL AX, 20(SP)
46
47 // Copy C arguments from original stack location to our frame
48 // Original args start at 304+4(SP) = 308(SP) (past our frame + original return addr)
49 // Copy to our frame at 36(SP)
50 // Copy 64 arguments (256 bytes, matching callbackMaxFrame = 64 * ptrSize)
51 MOVL 308(SP), AX
52 MOVL AX, 36(SP)
53 MOVL 312(SP), AX
54 MOVL AX, 40(SP)
55 MOVL 316(SP), AX
56 MOVL AX, 44(SP)
57 MOVL 320(SP), AX
58 MOVL AX, 48(SP)
59 MOVL 324(SP), AX
60 MOVL AX, 52(SP)
61 MOVL 328(SP), AX
62 MOVL AX, 56(SP)
63 MOVL 332(SP), AX
64 MOVL AX, 60(SP)
65 MOVL 336(SP), AX
66 MOVL AX, 64(SP)
67 MOVL 340(SP), AX
68 MOVL AX, 68(SP)
69 MOVL 344(SP), AX
70 MOVL AX, 72(SP)
71 MOVL 348(SP), AX
72 MOVL AX, 76(SP)
73 MOVL 352(SP), AX
74 MOVL AX, 80(SP)
75 MOVL 356(SP), AX
76 MOVL AX, 84(SP)
77 MOVL 360(SP), AX
78 MOVL AX, 88(SP)
79 MOVL 364(SP), AX
80 MOVL AX, 92(SP)
81 MOVL 368(SP), AX
82 MOVL AX, 96(SP)
83 MOVL 372(SP), AX
84 MOVL AX, 100(SP)
85 MOVL 376(SP), AX
86 MOVL AX, 104(SP)
87 MOVL 380(SP), AX
88 MOVL AX, 108(SP)
89 MOVL 384(SP), AX
90 MOVL AX, 112(SP)
91 MOVL 388(SP), AX
92 MOVL AX, 116(SP)
93 MOVL 392(SP), AX
94 MOVL AX, 120(SP)
95 MOVL 396(SP), AX
96 MOVL AX, 124(SP)
97 MOVL 400(SP), AX
98 MOVL AX, 128(SP)
99 MOVL 404(SP), AX
100 MOVL AX, 132(SP)
101 MOVL 408(SP), AX
102 MOVL AX, 136(SP)
103 MOVL 412(SP), AX
104 MOVL AX, 140(SP)
105 MOVL 416(SP), AX
106 MOVL AX, 144(SP)
107 MOVL 420(SP), AX
108 MOVL AX, 148(SP)
109 MOVL 424(SP), AX
110 MOVL AX, 152(SP)
111 MOVL 428(SP), AX
112 MOVL AX, 156(SP)
113 MOVL 432(SP), AX
114 MOVL AX, 160(SP)
115 MOVL 436(SP), AX
116 MOVL AX, 164(SP)
117 MOVL 440(SP), AX
118 MOVL AX, 168(SP)
119 MOVL 444(SP), AX
120 MOVL AX, 172(SP)
121 MOVL 448(SP), AX
122 MOVL AX, 176(SP)
123 MOVL 452(SP), AX
124 MOVL AX, 180(SP)
125 MOVL 456(SP), AX
126 MOVL AX, 184(SP)
127 MOVL 460(SP), AX
128 MOVL AX, 188(SP)
129 MOVL 464(SP), AX
130 MOVL AX, 192(SP)
131 MOVL 468(SP), AX
132 MOVL AX, 196(SP)
133 MOVL 472(SP), AX
134 MOVL AX, 200(SP)
135 MOVL 476(SP), AX
136 MOVL AX, 204(SP)
137 MOVL 480(SP), AX
138 MOVL AX, 208(SP)
139 MOVL 484(SP), AX
140 MOVL AX, 212(SP)
141 MOVL 488(SP), AX
142 MOVL AX, 216(SP)
143 MOVL 492(SP), AX
144 MOVL AX, 220(SP)
145 MOVL 496(SP), AX
146 MOVL AX, 224(SP)
147 MOVL 500(SP), AX
148 MOVL AX, 228(SP)
149 MOVL 504(SP), AX
150 MOVL AX, 232(SP)
151 MOVL 508(SP), AX
152 MOVL AX, 236(SP)
153 MOVL 512(SP), AX
154 MOVL AX, 240(SP)
155 MOVL 516(SP), AX
156 MOVL AX, 244(SP)
157 MOVL 520(SP), AX
158 MOVL AX, 248(SP)
159 MOVL 524(SP), AX
160 MOVL AX, 252(SP)
161 MOVL 528(SP), AX
162 MOVL AX, 256(SP)
163 MOVL 532(SP), AX
164 MOVL AX, 260(SP)
165 MOVL 536(SP), AX
166 MOVL AX, 264(SP)
167 MOVL 540(SP), AX
168 MOVL AX, 268(SP)
169 MOVL 544(SP), AX
170 MOVL AX, 272(SP)
171 MOVL 548(SP), AX
172 MOVL AX, 276(SP)
173 MOVL 552(SP), AX
174 MOVL AX, 280(SP)
175 MOVL 556(SP), AX
176 MOVL AX, 284(SP)
177 MOVL 560(SP), AX
178 MOVL AX, 288(SP)
179
180 // Set up callbackArgs struct at 24(SP)
181 // struct callbackArgs {
182 // index uintptr // offset 0
183 // args *byte // offset 4
184 // result uintptr // offset 8
185 // }
186 MOVL 16(SP), AX // callback index
187 MOVL AX, 24(SP) // callbackArgs.index
188 LEAL 36(SP), AX // pointer to copied arguments
189 MOVL AX, 28(SP) // callbackArgs.args
190 MOVL $0, 32(SP) // callbackArgs.result = 0
191
192 // Call crosscall2(fn, frame, 0, ctxt)
193 // crosscall2 expects arguments on stack:
194 // 0(SP) = fn
195 // 4(SP) = frame (pointer to callbackArgs)
196 // 8(SP) = ignored (was n)
197 // 12(SP) = ctxt
198 SUBL $16, SP
199
200 MOVL ·callbackWrap_call(SB), AX
201 MOVL (AX), AX // fn = *callbackWrap_call
202 MOVL AX, 0(SP) // fn
203 LEAL (24+16)(SP), AX // &callbackArgs (adjusted for SUB $16)
204 MOVL AX, 4(SP) // frame
205 MOVL $0, 8(SP) // 0
206 MOVL $0, 12(SP) // ctxt
207
208 CALL crosscall2(SB)
209
210 ADDL $16, SP
211
212 // Get result from callbackArgs.result
213 MOVL 32(SP), AX
214
215 // Restore callee-saved registers
216 MOVL 0(SP), BX
217 MOVL 4(SP), SI
218 MOVL 8(SP), DI
219 MOVL 12(SP), BP
220
221 // Restore return address and clean up
222 MOVL 20(SP), CX // get return address
223 ADDL $304, SP // remove our frame
224 MOVL CX, 0(SP) // put return address back
225
226 RET
227