1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
3
4//go:build !cgo && linux
5
6#include "textflag.h"
7#include "go_asm.h"
8#include "abi_ppc64x.h"
9
10// These trampolines map the C ABI to Go ABI and call into the Go equivalent functions.
11
12TEXT x_cgo_init_trampoline(SB), NOSPLIT, $0-0
13 MOVD ·x_cgo_init_call(SB), R12
14 MOVD (R12), R12
15 MOVD R12, CTR
16 CALL CTR
17 RET
18
19TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT, $0-0
20 MOVD ·x_cgo_thread_start_call(SB), R12
21 MOVD (R12), R12
22 MOVD R12, CTR
23 CALL CTR
24 RET
25
26TEXT x_cgo_setenv_trampoline(SB), NOSPLIT, $0-0
27 MOVD ·x_cgo_setenv_call(SB), R12
28 MOVD (R12), R12
29 MOVD R12, CTR
30 CALL CTR
31 RET
32
33TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT, $0-0
34 MOVD ·x_cgo_unsetenv_call(SB), R12
35 MOVD (R12), R12
36 MOVD R12, CTR
37 CALL CTR
38 RET
39
40TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT, $0-0
41 CALL ·x_cgo_notify_runtime_init_done(SB)
42 RET
43
44TEXT x_cgo_bindm_trampoline(SB), NOSPLIT, $0-0
45 CALL ·x_cgo_bindm(SB)
46 RET
47
48// func setg_trampoline(setg uintptr, g uintptr)
49TEXT ·setg_trampoline(SB), NOSPLIT, $16-16
50 MOVD R31, 8(R1) // save R31
51
52 MOVD setg+0(FP), R12
53 MOVD newg+8(FP), R3
54
55 MOVD R3, 16(R1) // save newg before call
56
57 MOVD R12, CTR
58 CALL CTR
59
60 // Assign g directly instead of calling runtime·load_g
61 // setg_gcc has already stored newg into TLS; put it in the g register too.
62 MOVD 16(R1), g
63
64 MOVD 8(R1), R31
65 XOR R0, R0, R0
66 RET
67
68TEXT threadentry_trampoline(SB), NOSPLIT|NOFRAME, $0-0
69 // Called from C (pthread_create). Must save all C callee-saved registers.
70 // Uses NOFRAME for proper ELFv2 backchain via MOVDU.
71 MOVD LR, R0
72 MOVD R0, 16(R1)
73 MOVW CR, R0
74 MOVD R0, 8(R1)
75
76 MOVDU R1, -320(R1)
77
78 SAVE_GPR(32)
79 SAVE_FPR(32+SAVE_GPR_SIZE)
80
81 MOVD $0, R0
82
83 MOVD ·threadentry_call(SB), R12
84 MOVD (R12), R12
85 MOVD R12, CTR
86 CALL CTR
87
88 RESTORE_FPR(32+SAVE_GPR_SIZE)
89 RESTORE_GPR(32)
90
91 ADD $320, R1
92
93 MOVD 16(R1), R0
94 MOVD R0, LR
95 MOVD 8(R1), R0
96 MOVW R0, CR
97 RET
98
99TEXT ·call5(SB), NOSPLIT|NOFRAME, $0-56
100 MOVD LR, R20
101 MOVW CR, R21
102
103 // Load arguments from Go stack into C argument registers
104 // Go placed args at 32(R1), 40(R1), etc.
105 MOVD 32(R1), R12 // fn
106 MOVD 40(R1), R3 // a1 → first C arg
107 MOVD 48(R1), R4 // a2 → second C arg
108 MOVD 56(R1), R5 // a3 → third C arg
109 MOVD 64(R1), R6 // a4 → fourth C arg
110 MOVD 72(R1), R7 // a5 → fifth C arg
111
112 MOVDU R1, -32(R1)
113
114 MOVD R12, CTR
115 CALL CTR
116
117 // Store return value
118 // After MOVDU -32, original 80(R1) is now at 80+32=112(R1)
119 MOVD R3, (80+32)(R1)
120
121 // Deallocate frame
122 ADD $32, R1
123
124 // Clear R0 before returning to Go code.
125 // Go uses R0 as a constant 0 register for things like "std r0,X(r1)"
126 // to zero stack locations. C functions may leave garbage in R0.
127 XOR R0, R0, R0
128
129 // Restore LR/CR from non-volatile registers
130 MOVD R20, LR
131 MOVW R21, CR
132 RET