forked from ebitengine/purego
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsys_amd64.s
135 lines (111 loc) · 3.88 KB
/
sys_amd64.s
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
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
//go:build darwin || (!cgo && linux)
#include "textflag.h"
#include "internal/abi/abi_amd64.h"
#include "go_asm.h"
#include "funcdata.h"
// syscall9X calls a function in libc on behalf of the syscall package.
// syscall9X takes a pointer to a struct like:
// struct {
// fn uintptr
// a1 uintptr
// a2 uintptr
// a3 uintptr
// a4 uintptr
// a5 uintptr
// a6 uintptr
// a7 uintptr
// a8 uintptr
// a9 uintptr
// r1 uintptr
// r2 uintptr
// err uintptr
// }
// syscall9X must be called on the g0 stack with the
// C calling convention (use libcCall).
GLOBL ·syscall9XABI0(SB), NOPTR|RODATA, $8
DATA ·syscall9XABI0(SB)/8, $syscall9X(SB)
TEXT syscall9X(SB), NOSPLIT, $0
PUSHQ BP
MOVQ SP, BP
SUBQ $32, SP
MOVQ DI, 24(BP) // save the pointer
MOVQ syscall9Args_f1(DI), X0 // f1
MOVQ syscall9Args_f2(DI), X1 // f2
MOVQ syscall9Args_f3(DI), X2 // f3
MOVQ syscall9Args_f4(DI), X3 // f4
MOVQ syscall9Args_f5(DI), X4 // f5
MOVQ syscall9Args_f6(DI), X5 // f6
MOVQ syscall9Args_f7(DI), X6 // f7
MOVQ syscall9Args_f8(DI), X7 // f8
MOVQ syscall9Args_fn(DI), R10 // fn
MOVQ syscall9Args_a2(DI), SI // a2
MOVQ syscall9Args_a3(DI), DX // a3
MOVQ syscall9Args_a4(DI), CX // a4
MOVQ syscall9Args_a5(DI), R8 // a5
MOVQ syscall9Args_a6(DI), R9 // a6
MOVQ syscall9Args_a7(DI), R11 // a7
MOVQ syscall9Args_a8(DI), R12 // a8
MOVQ syscall9Args_a9(DI), R13 // a9
MOVQ syscall9Args_a1(DI), DI // a1
// push the remaining paramters onto the stack
MOVQ R11, 0(SP) // push a7
MOVQ R12, 8(SP) // push a8
MOVQ R13, 16(SP) // push a9
XORL AX, AX // vararg: say "no float args"
CALL R10
MOVQ 24(BP), DI // get the pointer back
MOVQ AX, syscall9Args_r1(DI) // r1
MOVQ X0, syscall9Args_r2(DI) // r2
XORL AX, AX // no error (it's ignored anyway)
ADDQ $32, SP
MOVQ BP, SP
POPQ BP
RET
TEXT callbackasm1(SB), NOSPLIT, $0
// remove return address from stack, we are not returning to callbackasm, but to its caller.
MOVQ 0(SP), AX
ADDQ $8, SP
MOVQ 0(SP), R10 // get the return SP so that we can align register args with stack args
// make space for first six arguments below the frame
ADJSP $6*8, SP
MOVQ DI, 8(SP)
MOVQ SI, 16(SP)
MOVQ DX, 24(SP)
MOVQ CX, 32(SP)
MOVQ R8, 40(SP)
MOVQ R9, 48(SP)
LEAQ 8(SP), R8 // R8 = address of args vector
MOVQ R10, 0(SP) // push the stack pointer below registers
// determine index into runtime·cbs table
MOVQ $callbackasm(SB), DX
SUBQ DX, AX
MOVQ $0, DX
MOVQ $5, CX // divide by 5 because each call instruction in ·callbacks is 5 bytes long
DIVL CX
SUBQ $1, AX // subtract 1 because return PC is to the next slot
// Switch from the host ABI to the Go ABI.
PUSH_REGS_HOST_TO_ABI0()
// Create a struct callbackArgs on our stack to be passed as
// the "frame" to cgocallback and on to callbackWrap.
// $24 to make enough room for the arguments to runtime.cgocallback
SUBQ $(24+callbackArgs__size), SP
MOVQ AX, (24+callbackArgs_index)(SP) // callback index
MOVQ R8, (24+callbackArgs_args)(SP) // address of args vector
MOVQ $0, (24+callbackArgs_result)(SP) // result
LEAQ 24(SP), AX // take the address of callbackArgs
// Call cgocallback, which will call callbackWrap(frame).
MOVQ ·callbackWrap_call(SB), DI // Get the ABIInternal function pointer
MOVQ (DI), DI // without <ABIInternal> by using a closure.
MOVQ AX, SI // frame (address of callbackArgs)
MOVQ $0, CX // context
CALL crosscall2(SB) // runtime.cgocallback(fn, frame, ctxt uintptr)
// Get callback result.
MOVQ (24+callbackArgs_result)(SP), AX
ADDQ $(24+callbackArgs__size), SP // remove callbackArgs struct
POP_REGS_HOST_TO_ABI0()
MOVQ 0(SP), R10 // get the SP back
ADJSP $-6*8, SP // remove arguments
MOVQ R10, 0(SP)
RET