summaryrefslogtreecommitdiff
path: root/c/libffi_x86_x64/win64.asm
blob: 301188bc9c17f5142ada552eed6f676a5c0d3079 (plain)
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
148
149
150
151
152
153
154
155
156
PUBLIC	ffi_call_AMD64

EXTRN	__chkstk:NEAR
EXTRN	ffi_closure_SYSV:NEAR

_TEXT	SEGMENT

;;; ffi_closure_OUTER will be called with these registers set:
;;;    rax points to 'closure'
;;;    r11 contains a bit mask that specifies which of the
;;;    first four parameters are float or double
;;;
;;; It must move the parameters passed in registers to their stack location,
;;; call ffi_closure_SYSV for the actual work, then return the result.
;;; 
ffi_closure_OUTER PROC FRAME
	;; save actual arguments to their stack space.
	test	r11, 1
	jne	first_is_float	
	mov	QWORD PTR [rsp+8], rcx
	jmp	second
first_is_float:
	movlpd	QWORD PTR [rsp+8], xmm0

second:
	test	r11, 2
	jne	second_is_float	
	mov	QWORD PTR [rsp+16], rdx
	jmp	third
second_is_float:
	movlpd	QWORD PTR [rsp+16], xmm1

third:
	test	r11, 4
	jne	third_is_float	
	mov	QWORD PTR [rsp+24], r8
	jmp	forth
third_is_float:
	movlpd	QWORD PTR [rsp+24], xmm2

forth:
	test	r11, 8
	jne	forth_is_float	
	mov	QWORD PTR [rsp+32], r9
	jmp	done
forth_is_float:
	movlpd	QWORD PTR [rsp+32], xmm3

done:
.ALLOCSTACK 40
	sub	rsp, 40
.ENDPROLOG
	mov	rcx, rax	; context is first parameter
	mov	rdx, rsp	; stack is second parameter
	add	rdx, 40		; correct our own area
	mov	rax, ffi_closure_SYSV
	call	rax		; call the real closure function
	;; Here, code is missing that handles float return values
	add	rsp, 40
	movd	xmm0, rax	; In case the closure returned a float.
	ret	0
ffi_closure_OUTER ENDP


;;; ffi_call_AMD64

stack$ = 0
prepfunc$ = 32
ecif$ = 40
bytes$ = 48
flags$ = 56
rvalue$ = 64
fn$ = 72

ffi_call_AMD64 PROC FRAME

	mov	QWORD PTR [rsp+32], r9
	mov	QWORD PTR [rsp+24], r8
	mov	QWORD PTR [rsp+16], rdx
	mov	QWORD PTR [rsp+8], rcx
.PUSHREG rbp
	push	rbp
.ALLOCSTACK 48
	sub	rsp, 48					; 00000030H
.SETFRAME rbp, 32
	lea	rbp, QWORD PTR [rsp+32]
.ENDPROLOG

	mov	eax, DWORD PTR bytes$[rbp]
	add	rax, 15
	and	rax, -16
	call	__chkstk
	sub	rsp, rax
	lea	rax, QWORD PTR [rsp+32]
	mov	QWORD PTR stack$[rbp], rax

	mov	rdx, QWORD PTR ecif$[rbp]
	mov	rcx, QWORD PTR stack$[rbp]
	call	QWORD PTR prepfunc$[rbp]

	mov	rsp, QWORD PTR stack$[rbp]

	movlpd	xmm3, QWORD PTR [rsp+24]
	movd	r9, xmm3

	movlpd	xmm2, QWORD PTR [rsp+16]
	movd	r8, xmm2

	movlpd	xmm1, QWORD PTR [rsp+8]
	movd	rdx, xmm1

	movlpd	xmm0, QWORD PTR [rsp]
	movd	rcx, xmm0

	call	QWORD PTR fn$[rbp]
ret_int$:
 	cmp	DWORD PTR flags$[rbp], 1 ; FFI_TYPE_INT
 	jne	ret_float$

	mov	rcx, QWORD PTR rvalue$[rbp]
	mov	DWORD PTR [rcx], eax
	jmp	SHORT ret_nothing$

ret_float$:
 	cmp	DWORD PTR flags$[rbp], 2 ; FFI_TYPE_FLOAT
 	jne	SHORT ret_double$

 	mov	rax, QWORD PTR rvalue$[rbp]
 	movlpd	QWORD PTR [rax], xmm0
 	jmp	SHORT ret_nothing$

ret_double$:
 	cmp	DWORD PTR flags$[rbp], 3 ; FFI_TYPE_DOUBLE
 	jne	SHORT ret_int64$

 	mov	rax, QWORD PTR rvalue$[rbp]
 	movlpd	QWORD PTR [rax], xmm0
 	jmp	SHORT ret_nothing$

ret_int64$:
  	cmp	DWORD PTR flags$[rbp], 12 ; FFI_TYPE_SINT64
  	jne	ret_nothing$

 	mov	rcx, QWORD PTR rvalue$[rbp]
 	mov	QWORD PTR [rcx], rax
 	jmp	SHORT ret_nothing$
	
ret_nothing$:
	xor	eax, eax

	lea	rsp, QWORD PTR [rbp+16]
	pop	rbp
	ret	0
ffi_call_AMD64 ENDP
_TEXT	ENDS
END