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)
|