File: sys_arm.s

package info (click to toggle)
golang-github-ebitengine-purego 0.10.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,452 kB
  • sloc: asm: 31,862; ansic: 1,001; cpp: 8; makefile: 3
file content (142 lines) | stat: -rw-r--r-- 4,124 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2026 The Ebitengine Authors

//go:build linux

#include "textflag.h"
#include "go_asm.h"
#include "funcdata.h"

#define STACK_SIZE 128
#define PTR_ADDRESS (STACK_SIZE - 4)

// syscall15X calls a function in libc on behalf of the syscall package.
// syscall15X takes a pointer to a struct like:
// struct {
//	fn    uintptr
//	a1    uintptr
//  ...
//	a32   uintptr
//	f1    uintptr
//	...
//	f16   uintptr
//	arm64_r8 uintptr
// }
// syscall15X must be called on the g0 stack with the
// C calling convention (use libcCall).
GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $4
DATA ·syscall15XABI0(SB)/4, $syscall15X(SB)
TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0-0
	// Called via C calling convention: R0 = pointer to syscall15Args
	// NOT via Go calling convention
	// Save link register and callee-saved registers first
	MOVW.W    R14, -4(R13)                         // save LR (decrement and store)
	MOVM.DB.W [R4, R5, R6, R7, R8, R9, R11], (R13) // save callee-saved regs

	MOVW R0, R8
	SUB  $STACK_SIZE, R13
	MOVW R8, PTR_ADDRESS(R13)

	// Load function pointer first (before anything can corrupt R8)
	MOVW syscall15Args_fn(R8), R5
	MOVW R5, (PTR_ADDRESS-4)(R13) // save fn at offset 56

	// Load floating point arguments
	// Each float64 spans 2 uintptr slots (8 bytes) on ARM32, so we skip by 2
	MOVD syscall15Args_f1(R8), F0  // f1+f2 -> D0
	MOVD syscall15Args_f3(R8), F1  // f3+f4 -> D1
	MOVD syscall15Args_f5(R8), F2  // f5+f6 -> D2
	MOVD syscall15Args_f7(R8), F3  // f7+f8 -> D3
	MOVD syscall15Args_f9(R8), F4  // f9+f10 -> D4
	MOVD syscall15Args_f11(R8), F5 // f11+f12 -> D5
	MOVD syscall15Args_f13(R8), F6 // f13+f14 -> D6
	MOVD syscall15Args_f15(R8), F7 // f15+f16 -> D7

	// Load integer arguments into registers (R0-R3 for ARM EABI)
	MOVW syscall15Args_a1(R8), R0 // a1
	MOVW syscall15Args_a2(R8), R1 // a2
	MOVW syscall15Args_a3(R8), R2 // a3
	MOVW syscall15Args_a4(R8), R3 // a4

	// push a5-a32 onto stack
	MOVW syscall15Args_a5(R8), R4
	MOVW R4, 0(R13)
	MOVW syscall15Args_a6(R8), R4
	MOVW R4, 4(R13)
	MOVW syscall15Args_a7(R8), R4
	MOVW R4, 8(R13)
	MOVW syscall15Args_a8(R8), R4
	MOVW R4, 12(R13)
	MOVW syscall15Args_a9(R8), R4
	MOVW R4, 16(R13)
	MOVW syscall15Args_a10(R8), R4
	MOVW R4, 20(R13)
	MOVW syscall15Args_a11(R8), R4
	MOVW R4, 24(R13)
	MOVW syscall15Args_a12(R8), R4
	MOVW R4, 28(R13)
	MOVW syscall15Args_a13(R8), R4
	MOVW R4, 32(R13)
	MOVW syscall15Args_a14(R8), R4
	MOVW R4, 36(R13)
	MOVW syscall15Args_a15(R8), R4
	MOVW R4, 40(R13)
	MOVW syscall15Args_a16(R8), R4
	MOVW R4, 44(R13)
	MOVW syscall15Args_a17(R8), R4
	MOVW R4, 48(R13)
	MOVW syscall15Args_a18(R8), R4
	MOVW R4, 52(R13)
	MOVW syscall15Args_a19(R8), R4
	MOVW R4, 56(R13)
	MOVW syscall15Args_a20(R8), R4
	MOVW R4, 60(R13)
	MOVW syscall15Args_a21(R8), R4
	MOVW R4, 64(R13)
	MOVW syscall15Args_a22(R8), R4
	MOVW R4, 68(R13)
	MOVW syscall15Args_a23(R8), R4
	MOVW R4, 72(R13)
	MOVW syscall15Args_a24(R8), R4
	MOVW R4, 76(R13)
	MOVW syscall15Args_a25(R8), R4
	MOVW R4, 80(R13)
	MOVW syscall15Args_a26(R8), R4
	MOVW R4, 84(R13)
	MOVW syscall15Args_a27(R8), R4
	MOVW R4, 88(R13)
	MOVW syscall15Args_a28(R8), R4
	MOVW R4, 92(R13)
	MOVW syscall15Args_a29(R8), R4
	MOVW R4, 96(R13)
	MOVW syscall15Args_a30(R8), R4
	MOVW R4, 100(R13)
	MOVW syscall15Args_a31(R8), R4
	MOVW R4, 104(R13)
	MOVW syscall15Args_a32(R8), R4
	MOVW R4, 108(R13)

	// Load saved function pointer and call
	MOVW (PTR_ADDRESS-4)(R13), R4

	// Use BLX for Thumb interworking - Go assembler doesn't support BLX Rn
	// BLX R4 = 0xE12FFF34 (ARM encoding, always condition)
	WORD $0xE12FFF34 // blx r4

	// pop structure pointer
	MOVW PTR_ADDRESS(R13), R8
	ADD  $STACK_SIZE, R13

	// save R0, R1
	MOVW R0, syscall15Args_a1(R8)
	MOVW R1, syscall15Args_a2(R8)

	// save f0-f3 (each float64 spans 2 uintptr slots on ARM32)
	MOVD F0, syscall15Args_f1(R8)
	MOVD F1, syscall15Args_f3(R8)
	MOVD F2, syscall15Args_f5(R8)
	MOVD F3, syscall15Args_f7(R8)

	// Restore callee-saved registers and return
	MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, R11]
	MOVW.P    4(R13), R15                          // pop LR into PC (return)