sys_arm.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 #define STACK_SIZE 128
11 #define PTR_ADDRESS (STACK_SIZE - 4)
12
13 // syscall15X calls a function in libc on behalf of the syscall package.
14 // syscall15X takes a pointer to a struct like:
15 // struct {
16 // fn uintptr
17 // a1 uintptr
18 // ...
19 // a32 uintptr
20 // f1 uintptr
21 // ...
22 // f16 uintptr
23 // arm64_r8 uintptr
24 // }
25 // syscall15X must be called on the g0 stack with the
26 // C calling convention (use libcCall).
27 GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $4
28 DATA ·syscall15XABI0(SB)/4, $syscall15X(SB)
29 TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0-0
30 // Called via C calling convention: R0 = pointer to syscall15Args
31 // NOT via Go calling convention
32 // Save link register and callee-saved registers first
33 MOVW.W R14, -4(R13) // save LR (decrement and store)
34 MOVM.DB.W [R4, R5, R6, R7, R8, R9, R11], (R13) // save callee-saved regs
35
36 MOVW R0, R8
37 SUB $STACK_SIZE, R13
38 MOVW R8, PTR_ADDRESS(R13)
39
40 // Load function pointer first (before anything can corrupt R8)
41 MOVW syscall15Args_fn(R8), R5
42 MOVW R5, (PTR_ADDRESS-4)(R13) // save fn at offset 56
43
44 // Load floating point arguments
45 // Each float64 spans 2 uintptr slots (8 bytes) on ARM32, so we skip by 2
46 MOVD syscall15Args_f1(R8), F0 // f1+f2 -> D0
47 MOVD syscall15Args_f3(R8), F1 // f3+f4 -> D1
48 MOVD syscall15Args_f5(R8), F2 // f5+f6 -> D2
49 MOVD syscall15Args_f7(R8), F3 // f7+f8 -> D3
50 MOVD syscall15Args_f9(R8), F4 // f9+f10 -> D4
51 MOVD syscall15Args_f11(R8), F5 // f11+f12 -> D5
52 MOVD syscall15Args_f13(R8), F6 // f13+f14 -> D6
53 MOVD syscall15Args_f15(R8), F7 // f15+f16 -> D7
54
55 // Load integer arguments into registers (R0-R3 for ARM EABI)
56 MOVW syscall15Args_a1(R8), R0 // a1
57 MOVW syscall15Args_a2(R8), R1 // a2
58 MOVW syscall15Args_a3(R8), R2 // a3
59 MOVW syscall15Args_a4(R8), R3 // a4
60
61 // push a5-a32 onto stack
62 MOVW syscall15Args_a5(R8), R4
63 MOVW R4, 0(R13)
64 MOVW syscall15Args_a6(R8), R4
65 MOVW R4, 4(R13)
66 MOVW syscall15Args_a7(R8), R4
67 MOVW R4, 8(R13)
68 MOVW syscall15Args_a8(R8), R4
69 MOVW R4, 12(R13)
70 MOVW syscall15Args_a9(R8), R4
71 MOVW R4, 16(R13)
72 MOVW syscall15Args_a10(R8), R4
73 MOVW R4, 20(R13)
74 MOVW syscall15Args_a11(R8), R4
75 MOVW R4, 24(R13)
76 MOVW syscall15Args_a12(R8), R4
77 MOVW R4, 28(R13)
78 MOVW syscall15Args_a13(R8), R4
79 MOVW R4, 32(R13)
80 MOVW syscall15Args_a14(R8), R4
81 MOVW R4, 36(R13)
82 MOVW syscall15Args_a15(R8), R4
83 MOVW R4, 40(R13)
84 MOVW syscall15Args_a16(R8), R4
85 MOVW R4, 44(R13)
86 MOVW syscall15Args_a17(R8), R4
87 MOVW R4, 48(R13)
88 MOVW syscall15Args_a18(R8), R4
89 MOVW R4, 52(R13)
90 MOVW syscall15Args_a19(R8), R4
91 MOVW R4, 56(R13)
92 MOVW syscall15Args_a20(R8), R4
93 MOVW R4, 60(R13)
94 MOVW syscall15Args_a21(R8), R4
95 MOVW R4, 64(R13)
96 MOVW syscall15Args_a22(R8), R4
97 MOVW R4, 68(R13)
98 MOVW syscall15Args_a23(R8), R4
99 MOVW R4, 72(R13)
100 MOVW syscall15Args_a24(R8), R4
101 MOVW R4, 76(R13)
102 MOVW syscall15Args_a25(R8), R4
103 MOVW R4, 80(R13)
104 MOVW syscall15Args_a26(R8), R4
105 MOVW R4, 84(R13)
106 MOVW syscall15Args_a27(R8), R4
107 MOVW R4, 88(R13)
108 MOVW syscall15Args_a28(R8), R4
109 MOVW R4, 92(R13)
110 MOVW syscall15Args_a29(R8), R4
111 MOVW R4, 96(R13)
112 MOVW syscall15Args_a30(R8), R4
113 MOVW R4, 100(R13)
114 MOVW syscall15Args_a31(R8), R4
115 MOVW R4, 104(R13)
116 MOVW syscall15Args_a32(R8), R4
117 MOVW R4, 108(R13)
118
119 // Load saved function pointer and call
120 MOVW (PTR_ADDRESS-4)(R13), R4
121
122 // Use BLX for Thumb interworking - Go assembler doesn't support BLX Rn
123 // BLX R4 = 0xE12FFF34 (ARM encoding, always condition)
124 WORD $0xE12FFF34 // blx r4
125
126 // pop structure pointer
127 MOVW PTR_ADDRESS(R13), R8
128 ADD $STACK_SIZE, R13
129
130 // save R0, R1
131 MOVW R0, syscall15Args_a1(R8)
132 MOVW R1, syscall15Args_a2(R8)
133
134 // save f0-f3 (each float64 spans 2 uintptr slots on ARM32)
135 MOVD F0, syscall15Args_f1(R8)
136 MOVD F1, syscall15Args_f3(R8)
137 MOVD F2, syscall15Args_f5(R8)
138 MOVD F3, syscall15Args_f7(R8)
139
140 // Restore callee-saved registers and return
141 MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, R11]
142 MOVW.P 4(R13), R15 // pop LR into PC (return)
143