Home | History | Annotate | Download | only in x86
      1 #define LIBFFI_ASM
      2 #include <fficonfig.h>
      3 #include <ffi.h>
      4 
      5 /* Constants for ffi_call_win64 */
      6 #define STACK 0
      7 #define PREP_ARGS_FN 32
      8 #define ECIF 40
      9 #define CIF_BYTES 48
     10 #define CIF_FLAGS 56
     11 #define RVALUE 64
     12 #define FN 72
     13 
     14 /* ffi_call_win64 (void (*prep_args_fn)(char *, extended_cif *),
     15                    extended_cif *ecif, unsigned bytes, unsigned flags,
     16                    unsigned *rvalue, void (*fn)());
     17  */
     18 
     19 #ifdef _MSC_VER
     20 PUBLIC	ffi_call_win64
     21 
     22 EXTRN	__chkstk:NEAR
     23 EXTRN	ffi_closure_win64_inner:NEAR
     24 
     25 _TEXT	SEGMENT
     26 
     27 ;;; ffi_closure_win64 will be called with these registers set:
     28 ;;;    rax points to 'closure'
     29 ;;;    r11 contains a bit mask that specifies which of the
     30 ;;;    first four parameters are float or double
     31 ;;;
     32 ;;; It must move the parameters passed in registers to their stack location,
     33 ;;; call ffi_closure_win64_inner for the actual work, then return the result.
     34 ;;;
     35 ffi_closure_win64 PROC FRAME
     36 	;; copy register arguments onto stack
     37 	test	r11, 1
     38 	jne	first_is_float
     39 	mov	QWORD PTR [rsp+8], rcx
     40 	jmp	second
     41 first_is_float:
     42 	movlpd	QWORD PTR [rsp+8], xmm0
     43 
     44 second:
     45 	test	r11, 2
     46 	jne	second_is_float
     47 	mov	QWORD PTR [rsp+16], rdx
     48 	jmp	third
     49 second_is_float:
     50 	movlpd	QWORD PTR [rsp+16], xmm1
     51 
     52 third:
     53 	test	r11, 4
     54 	jne	third_is_float
     55 	mov	QWORD PTR [rsp+24], r8
     56 	jmp	fourth
     57 third_is_float:
     58 	movlpd	QWORD PTR [rsp+24], xmm2
     59 
     60 fourth:
     61 	test	r11, 8
     62 	jne	fourth_is_float
     63 	mov	QWORD PTR [rsp+32], r9
     64 	jmp	done
     65 fourth_is_float:
     66 	movlpd	QWORD PTR [rsp+32], xmm3
     67 
     68 done:
     69         .ALLOCSTACK 40
     70 	sub	rsp, 40
     71         .ENDPROLOG
     72 	mov	rcx, rax	; context is first parameter
     73 	mov	rdx, rsp	; stack is second parameter
     74 	add	rdx, 48		; point to start of arguments
     75 	mov	rax, ffi_closure_win64_inner
     76 	call	rax		; call the real closure function
     77 	add	rsp, 40
     78 	movd	xmm0, rax	; If the closure returned a float,
     79                                 ; ffi_closure_win64_inner wrote it to rax
     80 	ret	0
     81 ffi_closure_win64 ENDP
     82 
     83 ffi_call_win64 PROC FRAME
     84         ;; copy registers onto stack
     85 	mov	QWORD PTR [rsp+32], r9
     86 	mov	QWORD PTR [rsp+24], r8
     87 	mov	QWORD PTR [rsp+16], rdx
     88 	mov	QWORD PTR [rsp+8], rcx
     89         .PUSHREG rbp
     90 	push	rbp
     91         .ALLOCSTACK 48
     92 	sub	rsp, 48					; 00000030H
     93         .SETFRAME rbp, 32
     94 	lea	rbp, QWORD PTR [rsp+32]
     95         .ENDPROLOG
     96 
     97 	mov	eax, DWORD PTR CIF_BYTES[rbp]
     98 	add	rax, 15
     99 	and	rax, -16
    100 	call	__chkstk
    101 	sub	rsp, rax
    102 	lea	rax, QWORD PTR [rsp+32]
    103 	mov	QWORD PTR STACK[rbp], rax
    104 
    105 	mov	rdx, QWORD PTR ECIF[rbp]
    106 	mov	rcx, QWORD PTR STACK[rbp]
    107 	call	QWORD PTR PREP_ARGS_FN[rbp]
    108 
    109 	mov	rsp, QWORD PTR STACK[rbp]
    110 
    111 	movlpd	xmm3, QWORD PTR [rsp+24]
    112 	movd	r9, xmm3
    113 
    114 	movlpd	xmm2, QWORD PTR [rsp+16]
    115 	movd	r8, xmm2
    116 
    117 	movlpd	xmm1, QWORD PTR [rsp+8]
    118 	movd	rdx, xmm1
    119 
    120 	movlpd	xmm0, QWORD PTR [rsp]
    121 	movd	rcx, xmm0
    122 
    123 	call	QWORD PTR FN[rbp]
    124 ret_struct4b$:
    125  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_4B
    126  	jne	ret_struct2b$
    127 
    128 	mov	rcx, QWORD PTR RVALUE[rbp]
    129 	mov	DWORD PTR [rcx], eax
    130 	jmp	ret_void$
    131 
    132 ret_struct2b$:
    133  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_2B
    134  	jne	ret_struct1b$
    135 
    136 	mov	rcx, QWORD PTR RVALUE[rbp]
    137 	mov	WORD PTR [rcx], ax
    138 	jmp	ret_void$
    139 
    140 ret_struct1b$:
    141  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_1B
    142  	jne	ret_uint8$
    143 
    144 	mov	rcx, QWORD PTR RVALUE[rbp]
    145 	mov	BYTE PTR [rcx], al
    146 	jmp	ret_void$
    147 
    148 ret_uint8$:
    149  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT8
    150  	jne	ret_sint8$
    151 
    152 	mov	rcx, QWORD PTR RVALUE[rbp]
    153 	movzx   rax, al
    154 	mov	QWORD PTR [rcx], rax
    155 	jmp	ret_void$
    156 
    157 ret_sint8$:
    158  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT8
    159  	jne	ret_uint16$
    160 
    161 	mov	rcx, QWORD PTR RVALUE[rbp]
    162 	movsx   rax, al
    163 	mov	QWORD PTR [rcx], rax
    164 	jmp	ret_void$
    165 
    166 ret_uint16$:
    167  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT16
    168  	jne	ret_sint16$
    169 
    170 	mov	rcx, QWORD PTR RVALUE[rbp]
    171 	movzx   rax, ax
    172 	mov	QWORD PTR [rcx], rax
    173 	jmp	SHORT ret_void$
    174 
    175 ret_sint16$:
    176  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT16
    177  	jne	ret_uint32$
    178 
    179 	mov	rcx, QWORD PTR RVALUE[rbp]
    180 	movsx   rax, ax
    181 	mov	QWORD PTR [rcx], rax
    182 	jmp	SHORT ret_void$
    183 
    184 ret_uint32$:
    185  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT32
    186  	jne	ret_sint32$
    187 
    188 	mov	rcx, QWORD PTR RVALUE[rbp]
    189 	mov     eax, eax
    190 	mov	QWORD PTR [rcx], rax
    191 	jmp	SHORT ret_void$
    192 
    193 ret_sint32$:
    194  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT32
    195  	jne	ret_float$
    196 
    197 	mov	rcx, QWORD PTR RVALUE[rbp]
    198 	cdqe
    199 	mov	QWORD PTR [rcx], rax
    200 	jmp	SHORT ret_void$
    201 
    202 ret_float$:
    203  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_FLOAT
    204  	jne	SHORT ret_double$
    205 
    206  	mov	rax, QWORD PTR RVALUE[rbp]
    207  	movss	DWORD PTR [rax], xmm0
    208  	jmp	SHORT ret_void$
    209 
    210 ret_double$:
    211  	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_DOUBLE
    212  	jne	SHORT ret_sint64$
    213 
    214  	mov	rax, QWORD PTR RVALUE[rbp]
    215  	movlpd	QWORD PTR [rax], xmm0
    216  	jmp	SHORT ret_void$
    217 
    218 ret_sint64$:
    219   	cmp	DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT64
    220   	jne	ret_void$
    221 
    222  	mov	rcx, QWORD PTR RVALUE[rbp]
    223  	mov	QWORD PTR [rcx], rax
    224  	jmp	SHORT ret_void$
    225 
    226 ret_void$:
    227 	xor	rax, rax
    228 
    229 	lea	rsp, QWORD PTR [rbp+16]
    230 	pop	rbp
    231 	ret	0
    232 ffi_call_win64 ENDP
    233 _TEXT	ENDS
    234 END
    235 
    236 #else
    237 
    238 #ifdef SYMBOL_UNDERSCORE
    239 #define SYMBOL_NAME(name) _##name
    240 #else
    241 #define SYMBOL_NAME(name) name
    242 #endif
    243 
    244 .text
    245 
    246 .extern SYMBOL_NAME(ffi_closure_win64_inner)
    247 
    248 # ffi_closure_win64 will be called with these registers set:
    249 #    rax points to 'closure'
    250 #    r11 contains a bit mask that specifies which of the
    251 #    first four parameters are float or double
    252 #
    253 # It must move the parameters passed in registers to their stack location,
    254 # call ffi_closure_win64_inner for the actual work, then return the result.
    255 #
    256 	.balign 16
    257         .globl SYMBOL_NAME(ffi_closure_win64)
    258 SYMBOL_NAME(ffi_closure_win64):
    259 	# copy register arguments onto stack
    260 	test	$1,%r11
    261 	jne	.Lfirst_is_float
    262 	mov	%rcx, 8(%rsp)
    263 	jmp	.Lsecond
    264 .Lfirst_is_float:
    265 	movlpd	%xmm0, 8(%rsp)
    266 
    267 .Lsecond:
    268 	test	$2, %r11
    269 	jne	.Lsecond_is_float
    270 	mov	%rdx, 16(%rsp)
    271 	jmp	.Lthird
    272 .Lsecond_is_float:
    273 	movlpd	%xmm1, 16(%rsp)
    274 
    275 .Lthird:
    276 	test	$4, %r11
    277 	jne	.Lthird_is_float
    278 	mov	%r8,24(%rsp)
    279 	jmp	.Lfourth
    280 .Lthird_is_float:
    281 	movlpd	%xmm2, 24(%rsp)
    282 
    283 .Lfourth:
    284 	test	$8, %r11
    285 	jne	.Lfourth_is_float
    286 	mov	%r9, 32(%rsp)
    287 	jmp	.Ldone
    288 .Lfourth_is_float:
    289 	movlpd	%xmm3, 32(%rsp)
    290 
    291 .Ldone:
    292 #.ALLOCSTACK 40
    293 	sub	$40, %rsp
    294 #.ENDPROLOG
    295 	mov	%rax, %rcx	# context is first parameter
    296 	mov	%rsp, %rdx	# stack is second parameter
    297 	add	$48, %rdx	# point to start of arguments
    298 	mov	$SYMBOL_NAME(ffi_closure_win64_inner), %rax
    299 	callq	*%rax		# call the real closure function
    300 	add	$40, %rsp
    301 	movq	%rax, %xmm0	# If the closure returned a float,
    302                                 # ffi_closure_win64_inner wrote it to rax
    303 	retq
    304 .ffi_closure_win64_end:
    305 
    306 	.balign 16
    307         .globl	SYMBOL_NAME(ffi_call_win64)
    308 SYMBOL_NAME(ffi_call_win64):
    309         # copy registers onto stack
    310 	mov	%r9,32(%rsp)
    311 	mov	%r8,24(%rsp)
    312 	mov	%rdx,16(%rsp)
    313 	mov	%rcx,8(%rsp)
    314         #.PUSHREG rbp
    315 	push	%rbp
    316         #.ALLOCSTACK 48
    317 	sub	$48,%rsp
    318         #.SETFRAME rbp, 32
    319 	lea	32(%rsp),%rbp
    320         #.ENDPROLOG
    321 
    322 	mov	CIF_BYTES(%rbp),%eax
    323 	add	$15, %rax
    324 	and	$-16, %rax
    325 	cmpq	$0x1000, %rax
    326 	jb	Lch_done
    327 Lch_probe:
    328 	subq	$0x1000,%rsp
    329 	orl	$0x0, (%rsp)
    330 	subq	$0x1000,%rax
    331 	cmpq	$0x1000,%rax
    332 	ja	Lch_probe
    333 Lch_done:
    334 	subq	%rax, %rsp
    335 	orl	$0x0, (%rsp)
    336 	lea	32(%rsp), %rax
    337 	mov	%rax, STACK(%rbp)
    338 
    339 	mov	ECIF(%rbp), %rdx
    340 	mov	STACK(%rbp), %rcx
    341 	callq	*PREP_ARGS_FN(%rbp)
    342 
    343 	mov	STACK(%rbp), %rsp
    344 
    345 	movlpd	24(%rsp), %xmm3
    346 	movd	%xmm3, %r9
    347 
    348 	movlpd	16(%rsp), %xmm2
    349 	movd	%xmm2, %r8
    350 
    351 	movlpd	8(%rsp), %xmm1
    352 	movd	%xmm1, %rdx
    353 
    354 	movlpd	(%rsp), %xmm0
    355 	movd	%xmm0, %rcx
    356 
    357 	callq	*FN(%rbp)
    358 .Lret_struct4b:
    359  	cmpl	$FFI_TYPE_SMALL_STRUCT_4B, CIF_FLAGS(%rbp)
    360  	jne .Lret_struct2b
    361 
    362 	mov	RVALUE(%rbp), %rcx
    363 	mov	%eax, (%rcx)
    364 	jmp	.Lret_void
    365 
    366 .Lret_struct2b:
    367 	cmpl	$FFI_TYPE_SMALL_STRUCT_2B, CIF_FLAGS(%rbp)
    368 	jne .Lret_struct1b
    369 
    370 	mov	RVALUE(%rbp), %rcx
    371 	mov	%ax, (%rcx)
    372 	jmp .Lret_void
    373 
    374 .Lret_struct1b:
    375 	cmpl	$FFI_TYPE_SMALL_STRUCT_1B, CIF_FLAGS(%rbp)
    376 	jne .Lret_uint8
    377 
    378 	mov	RVALUE(%rbp), %rcx
    379 	mov	%al, (%rcx)
    380 	jmp .Lret_void
    381 
    382 .Lret_uint8:
    383 	cmpl	$FFI_TYPE_UINT8, CIF_FLAGS(%rbp)
    384 	jne .Lret_sint8
    385 
    386         mov     RVALUE(%rbp), %rcx
    387         movzbq  %al, %rax
    388 	movq    %rax, (%rcx)
    389 	jmp .Lret_void
    390 
    391 .Lret_sint8:
    392 	cmpl	$FFI_TYPE_SINT8, CIF_FLAGS(%rbp)
    393 	jne .Lret_uint16
    394 
    395         mov     RVALUE(%rbp), %rcx
    396         movsbq  %al, %rax
    397 	movq    %rax, (%rcx)
    398 	jmp .Lret_void
    399 
    400 .Lret_uint16:
    401 	cmpl	$FFI_TYPE_UINT16, CIF_FLAGS(%rbp)
    402 	jne .Lret_sint16
    403 
    404         mov     RVALUE(%rbp), %rcx
    405         movzwq  %ax, %rax
    406 	movq    %rax, (%rcx)
    407 	jmp .Lret_void
    408 
    409 .Lret_sint16:
    410 	cmpl	$FFI_TYPE_SINT16, CIF_FLAGS(%rbp)
    411 	jne .Lret_uint32
    412 
    413         mov     RVALUE(%rbp), %rcx
    414         movswq  %ax, %rax
    415 	movq    %rax, (%rcx)
    416 	jmp .Lret_void
    417 
    418 .Lret_uint32:
    419 	cmpl	$FFI_TYPE_UINT32, CIF_FLAGS(%rbp)
    420 	jne .Lret_sint32
    421 
    422         mov     RVALUE(%rbp), %rcx
    423         movl    %eax, %eax
    424 	movq    %rax, (%rcx)
    425 	jmp .Lret_void
    426 
    427 .Lret_sint32:
    428  	cmpl	$FFI_TYPE_SINT32, CIF_FLAGS(%rbp)
    429  	jne	.Lret_float
    430 
    431 	mov	RVALUE(%rbp), %rcx
    432 	cltq
    433 	movq	%rax, (%rcx)
    434 	jmp	.Lret_void
    435 
    436 .Lret_float:
    437  	cmpl	$FFI_TYPE_FLOAT, CIF_FLAGS(%rbp)
    438  	jne	.Lret_double
    439 
    440  	mov	RVALUE(%rbp), %rax
    441  	movss	%xmm0, (%rax)
    442  	jmp	.Lret_void
    443 
    444 .Lret_double:
    445  	cmpl	$FFI_TYPE_DOUBLE, CIF_FLAGS(%rbp)
    446  	jne	.Lret_sint64
    447 
    448  	mov	RVALUE(%rbp), %rax
    449  	movlpd	%xmm0, (%rax)
    450  	jmp	.Lret_void
    451 
    452 .Lret_sint64:
    453   	cmpl	$FFI_TYPE_SINT64, CIF_FLAGS(%rbp)
    454   	jne	.Lret_void
    455 
    456  	mov	RVALUE(%rbp), %rcx
    457  	mov	%rax, (%rcx)
    458  	jmp	.Lret_void
    459 
    460 .Lret_void:
    461 	xor	%rax, %rax
    462 
    463 	lea	16(%rbp), %rsp
    464 	pop	%rbp
    465 	retq
    466 .ffi_call_win64_end:
    467 #endif /* !_MSC_VER */
    468 
    469