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 143 144 145 146 147
|
// 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 160
#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).
//
// On i386 System V ABI, all arguments are passed on the stack.
// Return value is in EAX (and EDX for 64-bit values).
GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $4
DATA ·syscall15XABI0(SB)/4, $syscall15X(SB)
TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0-0
// Called via C calling convention: argument pointer at 4(SP)
// NOT via Go calling convention
// On i386, the first argument is at 4(SP) after CALL pushes return address
MOVL 4(SP), AX // get pointer to syscall15Args
// Save callee-saved registers
PUSHL BP
PUSHL BX
PUSHL SI
PUSHL DI
MOVL AX, BX // save args pointer in BX
// Allocate stack space for C function arguments
// i386 SysV: all 32 args on stack = 32 * 4 = 128 bytes
// Plus 16 bytes for alignment and local storage
SUBL $STACK_SIZE, SP
MOVL BX, PTR_ADDRESS(SP) // save args pointer
// Load function pointer
MOVL syscall15Args_fn(BX), AX
MOVL AX, (PTR_ADDRESS-4)(SP) // save fn pointer
// Push all integer arguments onto the stack (a1-a32)
// i386 SysV ABI: arguments pushed right-to-left, but we're
// setting up the stack from low to high addresses
MOVL syscall15Args_a1(BX), AX
MOVL AX, 0(SP)
MOVL syscall15Args_a2(BX), AX
MOVL AX, 4(SP)
MOVL syscall15Args_a3(BX), AX
MOVL AX, 8(SP)
MOVL syscall15Args_a4(BX), AX
MOVL AX, 12(SP)
MOVL syscall15Args_a5(BX), AX
MOVL AX, 16(SP)
MOVL syscall15Args_a6(BX), AX
MOVL AX, 20(SP)
MOVL syscall15Args_a7(BX), AX
MOVL AX, 24(SP)
MOVL syscall15Args_a8(BX), AX
MOVL AX, 28(SP)
MOVL syscall15Args_a9(BX), AX
MOVL AX, 32(SP)
MOVL syscall15Args_a10(BX), AX
MOVL AX, 36(SP)
MOVL syscall15Args_a11(BX), AX
MOVL AX, 40(SP)
MOVL syscall15Args_a12(BX), AX
MOVL AX, 44(SP)
MOVL syscall15Args_a13(BX), AX
MOVL AX, 48(SP)
MOVL syscall15Args_a14(BX), AX
MOVL AX, 52(SP)
MOVL syscall15Args_a15(BX), AX
MOVL AX, 56(SP)
MOVL syscall15Args_a16(BX), AX
MOVL AX, 60(SP)
MOVL syscall15Args_a17(BX), AX
MOVL AX, 64(SP)
MOVL syscall15Args_a18(BX), AX
MOVL AX, 68(SP)
MOVL syscall15Args_a19(BX), AX
MOVL AX, 72(SP)
MOVL syscall15Args_a20(BX), AX
MOVL AX, 76(SP)
MOVL syscall15Args_a21(BX), AX
MOVL AX, 80(SP)
MOVL syscall15Args_a22(BX), AX
MOVL AX, 84(SP)
MOVL syscall15Args_a23(BX), AX
MOVL AX, 88(SP)
MOVL syscall15Args_a24(BX), AX
MOVL AX, 92(SP)
MOVL syscall15Args_a25(BX), AX
MOVL AX, 96(SP)
MOVL syscall15Args_a26(BX), AX
MOVL AX, 100(SP)
MOVL syscall15Args_a27(BX), AX
MOVL AX, 104(SP)
MOVL syscall15Args_a28(BX), AX
MOVL AX, 108(SP)
MOVL syscall15Args_a29(BX), AX
MOVL AX, 112(SP)
MOVL syscall15Args_a30(BX), AX
MOVL AX, 116(SP)
MOVL syscall15Args_a31(BX), AX
MOVL AX, 120(SP)
MOVL syscall15Args_a32(BX), AX
MOVL AX, 124(SP)
// Call the C function
MOVL (PTR_ADDRESS-4)(SP), AX
CALL AX
// Get args pointer back and save results
MOVL PTR_ADDRESS(SP), BX
MOVL AX, syscall15Args_a1(BX) // return value r1
MOVL DX, syscall15Args_a2(BX) // return value r2 (for 64-bit returns)
// Save x87 FPU return value (ST0) to f1 field
// On i386 System V ABI, float/double returns are in ST(0)
// We save as float64 (8 bytes) to preserve precision
FMOVDP F0, syscall15Args_f1(BX)
// Clean up stack
ADDL $STACK_SIZE, SP
// Restore callee-saved registers
POPL DI
POPL SI
POPL BX
POPL BP
RET
|