Microsoft Visual C port

This commit is contained in:
Anthony Green
2010-01-15 10:46:51 -05:00
parent 0739e7dc00
commit cadeba6cb5
14 changed files with 4081 additions and 259 deletions

View File

@@ -2,6 +2,7 @@
win32.S - Copyright (c) 1996, 1998, 2001, 2002, 2009 Red Hat, Inc.
Copyright (c) 2001 John Beniton
Copyright (c) 2002 Ranjit Mathew
Copyright (c) 2009 Daniel Witte
X86 Foreign Function Interface
@@ -31,14 +32,371 @@
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
#ifdef _MSC_VER
.386
.MODEL FLAT, C
EXTRN ffi_closure_SYSV_inner:NEAR
_TEXT SEGMENT
ffi_call_win32 PROC NEAR,
ffi_prep_args : NEAR PTR DWORD,
ecif : NEAR PTR DWORD,
cif_bytes : DWORD,
cif_flags : DWORD,
rvalue : NEAR PTR DWORD,
fn : NEAR PTR DWORD
;; Make room for all of the new args.
mov ecx, cif_bytes
sub esp, ecx
mov eax, esp
;; Place all of the ffi_prep_args in position
push ecif
push eax
call ffi_prep_args
;; Return stack to previous state and call the function
add esp, 8
call fn
;; cdecl: we restore esp in the epilogue, so there's no need to
;; remove the space we pushed for the args.
;; stdcall: the callee has already cleaned the stack.
;; Load ecx with the return type code
mov ecx, cif_flags
;; If the return value pointer is NULL, assume no return value.
cmp rvalue, 0
jne ca_jumptable
;; Even if there is no space for the return value, we are
;; obliged to handle floating-point values.
cmp ecx, FFI_TYPE_FLOAT
jne ca_epilogue
fstp st(0)
jmp ca_epilogue
ca_jumptable:
jmp [ca_jumpdata + 4 * ecx]
ca_jumpdata:
;; Do not insert anything here between label and jump table.
dd offset ca_epilogue ;; FFI_TYPE_VOID
dd offset ca_retint ;; FFI_TYPE_INT
dd offset ca_retfloat ;; FFI_TYPE_FLOAT
dd offset ca_retdouble ;; FFI_TYPE_DOUBLE
dd offset ca_retlongdouble ;; FFI_TYPE_LONGDOUBLE
dd offset ca_retint8 ;; FFI_TYPE_UINT8
dd offset ca_retint8 ;; FFI_TYPE_SINT8
dd offset ca_retint16 ;; FFI_TYPE_UINT16
dd offset ca_retint16 ;; FFI_TYPE_SINT16
dd offset ca_retint ;; FFI_TYPE_UINT32
dd offset ca_retint ;; FFI_TYPE_SINT32
dd offset ca_retint64 ;; FFI_TYPE_UINT64
dd offset ca_retint64 ;; FFI_TYPE_SINT64
dd offset ca_epilogue ;; FFI_TYPE_STRUCT
dd offset ca_retint ;; FFI_TYPE_POINTER
dd offset ca_retint8 ;; FFI_TYPE_SMALL_STRUCT_1B
dd offset ca_retint16 ;; FFI_TYPE_SMALL_STRUCT_2B
dd offset ca_retint ;; FFI_TYPE_SMALL_STRUCT_4B
ca_retint8:
;; Load %ecx with the pointer to storage for the return value
mov ecx, rvalue
mov [ecx + 0], al
jmp ca_epilogue
ca_retint16:
;; Load %ecx with the pointer to storage for the return value
mov ecx, rvalue
mov [ecx + 0], ax
jmp ca_epilogue
ca_retint:
;; Load %ecx with the pointer to storage for the return value
mov ecx, rvalue
mov [ecx + 0], eax
jmp ca_epilogue
ca_retint64:
;; Load %ecx with the pointer to storage for the return value
mov ecx, rvalue
mov [ecx + 0], eax
mov [ecx + 4], edx
jmp ca_epilogue
ca_retfloat:
;; Load %ecx with the pointer to storage for the return value
mov ecx, rvalue
fstp DWORD PTR [ecx]
jmp ca_epilogue
ca_retdouble:
;; Load %ecx with the pointer to storage for the return value
mov ecx, rvalue
fstp QWORD PTR [ecx]
jmp ca_epilogue
ca_retlongdouble:
;; Load %ecx with the pointer to storage for the return value
mov ecx, rvalue
fstp TBYTE PTR [ecx]
jmp ca_epilogue
ca_epilogue:
;; Epilogue code is autogenerated.
ret
ffi_call_win32 ENDP
ffi_closure_SYSV PROC NEAR FORCEFRAME
;; the ffi_closure ctx is passed in eax by the trampoline.
sub esp, 40
lea edx, [ebp - 24]
mov [ebp - 12], edx ;; resp
lea edx, [ebp + 8]
mov [esp + 8], edx ;; args
lea edx, [ebp - 12]
mov [esp + 4], edx ;; &resp
mov [esp], eax ;; closure
call ffi_closure_SYSV_inner
mov ecx, [ebp - 12]
cs_jumptable:
jmp [cs_jumpdata + 4 * eax]
cs_jumpdata:
;; Do not insert anything here between the label and jump table.
dd offset cs_epilogue ;; FFI_TYPE_VOID
dd offset cs_retint ;; FFI_TYPE_INT
dd offset cs_retfloat ;; FFI_TYPE_FLOAT
dd offset cs_retdouble ;; FFI_TYPE_DOUBLE
dd offset cs_retlongdouble ;; FFI_TYPE_LONGDOUBLE
dd offset cs_retint8 ;; FFI_TYPE_UINT8
dd offset cs_retint8 ;; FFI_TYPE_SINT8
dd offset cs_retint16 ;; FFI_TYPE_UINT16
dd offset cs_retint16 ;; FFI_TYPE_SINT16
dd offset cs_retint ;; FFI_TYPE_UINT32
dd offset cs_retint ;; FFI_TYPE_SINT32
dd offset cs_retint64 ;; FFI_TYPE_UINT64
dd offset cs_retint64 ;; FFI_TYPE_SINT64
dd offset cs_retstruct ;; FFI_TYPE_STRUCT
dd offset cs_retint ;; FFI_TYPE_POINTER
dd offset cs_retint8 ;; FFI_TYPE_SMALL_STRUCT_1B
dd offset cs_retint16 ;; FFI_TYPE_SMALL_STRUCT_2B
dd offset cs_retint ;; FFI_TYPE_SMALL_STRUCT_4B
cs_retint8:
mov al, [ecx]
jmp cs_epilogue
cs_retint16:
mov ax, [ecx]
jmp cs_epilogue
cs_retint:
mov eax, [ecx]
jmp cs_epilogue
cs_retint64:
mov eax, [ecx + 0]
mov edx, [ecx + 4]
jmp cs_epilogue
cs_retfloat:
fld DWORD PTR [ecx]
jmp cs_epilogue
cs_retdouble:
fld QWORD PTR [ecx]
jmp cs_epilogue
cs_retlongdouble:
fld TBYTE PTR [ecx]
jmp cs_epilogue
cs_retstruct:
;; Caller expects us to pop struct return value pointer hidden arg.
;; Epilogue code is autogenerated.
ret 4
cs_epilogue:
;; Epilogue code is autogenerated.
ret
ffi_closure_SYSV ENDP
#if !FFI_NO_RAW_API
#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) AND NOT 3)
#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
#define CIF_FLAGS_OFFSET 20
ffi_closure_raw_SYSV PROC NEAR USES esi
;; the ffi_closure ctx is passed in eax by the trampoline.
sub esp, 40
mov esi, [eax + RAW_CLOSURE_CIF_OFFSET] ;; closure->cif
mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data
mov [esp + 12], edx ;; user_data
lea edx, [ebp + 8]
mov [esp + 8], edx ;; raw_args
lea edx, [ebp - 24]
mov [esp + 4], edx ;; &res
mov [esp], esi ;; cif
call DWORD PTR [eax + RAW_CLOSURE_FUN_OFFSET] ;; closure->fun
mov eax, [esi + CIF_FLAGS_OFFSET] ;; cif->flags
lea ecx, [ebp - 24]
cr_jumptable:
jmp [cr_jumpdata + 4 * eax]
cr_jumpdata:
;; Do not insert anything here between the label and jump table.
dd offset cr_epilogue ;; FFI_TYPE_VOID
dd offset cr_retint ;; FFI_TYPE_INT
dd offset cr_retfloat ;; FFI_TYPE_FLOAT
dd offset cr_retdouble ;; FFI_TYPE_DOUBLE
dd offset cr_retlongdouble ;; FFI_TYPE_LONGDOUBLE
dd offset cr_retint8 ;; FFI_TYPE_UINT8
dd offset cr_retint8 ;; FFI_TYPE_SINT8
dd offset cr_retint16 ;; FFI_TYPE_UINT16
dd offset cr_retint16 ;; FFI_TYPE_SINT16
dd offset cr_retint ;; FFI_TYPE_UINT32
dd offset cr_retint ;; FFI_TYPE_SINT32
dd offset cr_retint64 ;; FFI_TYPE_UINT64
dd offset cr_retint64 ;; FFI_TYPE_SINT64
dd offset cr_epilogue ;; FFI_TYPE_STRUCT
dd offset cr_retint ;; FFI_TYPE_POINTER
dd offset cr_retint8 ;; FFI_TYPE_SMALL_STRUCT_1B
dd offset cr_retint16 ;; FFI_TYPE_SMALL_STRUCT_2B
dd offset cr_retint ;; FFI_TYPE_SMALL_STRUCT_4B
cr_retint8:
mov al, [ecx]
jmp cr_epilogue
cr_retint16:
mov ax, [ecx]
jmp cr_epilogue
cr_retint:
mov eax, [ecx]
jmp cr_epilogue
cr_retint64:
mov eax, [ecx + 0]
mov edx, [ecx + 4]
jmp cr_epilogue
cr_retfloat:
fld DWORD PTR [ecx]
jmp cr_epilogue
cr_retdouble:
fld QWORD PTR [ecx]
jmp cr_epilogue
cr_retlongdouble:
fld TBYTE PTR [ecx]
jmp cr_epilogue
cr_epilogue:
;; Epilogue code is autogenerated.
ret
ffi_closure_raw_SYSV ENDP
#endif /* !FFI_NO_RAW_API */
ffi_closure_STDCALL PROC NEAR FORCEFRAME
;; the ffi_closure ctx is passed in eax by the trampoline.
sub esp, 40
lea edx, [ebp - 24]
mov [ebp - 12], edx ;; resp
lea edx, [ebp + 12] ;; account for stub return address on stack
mov [esp + 8], edx ;; args
lea edx, [ebp - 12]
mov [esp + 4], edx ;; &resp
mov [esp], eax ;; closure
call ffi_closure_SYSV_inner
mov ecx, [ebp - 12]
cd_jumptable:
jmp [cd_jumpdata + 4 * eax]
cd_jumpdata:
;; Do not insert anything here between the label and jump table.
dd offset cd_epilogue ;; FFI_TYPE_VOID
dd offset cd_retint ;; FFI_TYPE_INT
dd offset cd_retfloat ;; FFI_TYPE_FLOAT
dd offset cd_retdouble ;; FFI_TYPE_DOUBLE
dd offset cd_retlongdouble ;; FFI_TYPE_LONGDOUBLE
dd offset cd_retint8 ;; FFI_TYPE_UINT8
dd offset cd_retint8 ;; FFI_TYPE_SINT8
dd offset cd_retint16 ;; FFI_TYPE_UINT16
dd offset cd_retint16 ;; FFI_TYPE_SINT16
dd offset cd_retint ;; FFI_TYPE_UINT32
dd offset cd_retint ;; FFI_TYPE_SINT32
dd offset cd_retint64 ;; FFI_TYPE_UINT64
dd offset cd_retint64 ;; FFI_TYPE_SINT64
dd offset cd_epilogue ;; FFI_TYPE_STRUCT
dd offset cd_retint ;; FFI_TYPE_POINTER
dd offset cd_retint8 ;; FFI_TYPE_SMALL_STRUCT_1B
dd offset cd_retint16 ;; FFI_TYPE_SMALL_STRUCT_2B
dd offset cd_retint ;; FFI_TYPE_SMALL_STRUCT_4B
cd_retint8:
mov al, [ecx]
jmp cd_epilogue
cd_retint16:
mov ax, [ecx]
jmp cd_epilogue
cd_retint:
mov eax, [ecx]
jmp cd_epilogue
cd_retint64:
mov eax, [ecx + 0]
mov edx, [ecx + 4]
jmp cd_epilogue
cd_retfloat:
fld DWORD PTR [ecx]
jmp cd_epilogue
cd_retdouble:
fld QWORD PTR [ecx]
jmp cd_epilogue
cd_retlongdouble:
fld TBYTE PTR [ecx]
jmp cd_epilogue
cd_epilogue:
;; Epilogue code is autogenerated.
ret
ffi_closure_STDCALL ENDP
_TEXT ENDS
END
#else
.text
# This assumes we are using gas.
.balign 16
.globl _ffi_call_SYSV
.def _ffi_call_SYSV; .scl 2; .type 32; .endef
_ffi_call_SYSV:
.globl _ffi_call_win32
.def _ffi_call_win32; .scl 2; .type 32; .endef
_ffi_call_win32:
.LFB1:
pushl %ebp
.LCFI0:
@@ -61,8 +419,10 @@ _ffi_call_SYSV:
# FIXME: Align the stack to a 128-bit boundary to avoid
# potential performance hits.
call *28(%ebp)
call *28(%ebp)
# stdcall functions pop arguments off the stack themselves
# Load %ecx with the return type code
movl 20(%ebp),%ecx
@@ -181,162 +541,9 @@ _ffi_call_SYSV:
movl %ebp,%esp
popl %ebp
ret
.ffi_call_SYSV_end:
.ffi_call_win32_end:
.LFE1:
# This assumes we are using gas.
.balign 16
.globl _ffi_call_STDCALL
.def _ffi_call_STDCALL; .scl 2; .type 32; .endef
_ffi_call_STDCALL:
.LFB2:
pushl %ebp
.LCFI2:
movl %esp,%ebp
.LCFI3:
# Make room for all of the new args.
movl 16(%ebp),%ecx
subl %ecx,%esp
movl %esp,%eax
# Place all of the ffi_prep_args in position
pushl 12(%ebp)
pushl %eax
call *8(%ebp)
# Return stack to previous state and call the function
addl $8,%esp
# FIXME: Align the stack to a 128-bit boundary to avoid
# potential performance hits.
call *28(%ebp)
# stdcall functions pop arguments off the stack themselves
# Load %ecx with the return type code
movl 20(%ebp),%ecx
# If the return value pointer is NULL, assume no return value.
cmpl $0,24(%ebp)
jne 0f
# Even if there is no space for the return value, we are
# obliged to handle floating-point values.
cmpl $FFI_TYPE_FLOAT,%ecx
jne .Lsc_noretval
fstp %st(0)
jmp .Lsc_epilogue
0:
call 1f
# Do not insert anything here between the call and the jump table.
.Lsc_store_table:
.long .Lsc_noretval /* FFI_TYPE_VOID */
.long .Lsc_retint /* FFI_TYPE_INT */
.long .Lsc_retfloat /* FFI_TYPE_FLOAT */
.long .Lsc_retdouble /* FFI_TYPE_DOUBLE */
.long .Lsc_retlongdouble /* FFI_TYPE_LONGDOUBLE */
.long .Lsc_retuint8 /* FFI_TYPE_UINT8 */
.long .Lsc_retsint8 /* FFI_TYPE_SINT8 */
.long .Lsc_retuint16 /* FFI_TYPE_UINT16 */
.long .Lsc_retsint16 /* FFI_TYPE_SINT16 */
.long .Lsc_retint /* FFI_TYPE_UINT32 */
.long .Lsc_retint /* FFI_TYPE_SINT32 */
.long .Lsc_retint64 /* FFI_TYPE_UINT64 */
.long .Lsc_retint64 /* FFI_TYPE_SINT64 */
.long .Lsc_retstruct /* FFI_TYPE_STRUCT */
.long .Lsc_retint /* FFI_TYPE_POINTER */
.long .Lsc_retstruct1b /* FFI_TYPE_SMALL_STRUCT_1B */
.long .Lsc_retstruct2b /* FFI_TYPE_SMALL_STRUCT_2B */
.long .Lsc_retstruct4b /* FFI_TYPE_SMALL_STRUCT_4B */
1:
add %ecx, %ecx
add %ecx, %ecx
add (%esp),%ecx
add $4, %esp
jmp *(%ecx)
/* Sign/zero extend as appropriate. */
.Lsc_retsint8:
movsbl %al, %eax
jmp .Lsc_retint
.Lsc_retsint16:
movswl %ax, %eax
jmp .Lsc_retint
.Lsc_retuint8:
movzbl %al, %eax
jmp .Lsc_retint
.Lsc_retuint16:
movzwl %ax, %eax
jmp .Lsc_retint
.Lsc_retint:
# Load %ecx with the pointer to storage for the return value
movl 24(%ebp),%ecx
movl %eax,0(%ecx)
jmp .Lsc_epilogue
.Lsc_retfloat:
# Load %ecx with the pointer to storage for the return value
movl 24(%ebp),%ecx
fstps (%ecx)
jmp .Lsc_epilogue
.Lsc_retdouble:
# Load %ecx with the pointer to storage for the return value
movl 24(%ebp),%ecx
fstpl (%ecx)
jmp .Lsc_epilogue
.Lsc_retlongdouble:
# Load %ecx with the pointer to storage for the return value
movl 24(%ebp),%ecx
fstpt (%ecx)
jmp .Lsc_epilogue
.Lsc_retint64:
# Load %ecx with the pointer to storage for the return value
movl 24(%ebp),%ecx
movl %eax,0(%ecx)
movl %edx,4(%ecx)
jmp .Lsc_epilogue
.Lsc_retstruct1b:
# Load %ecx with the pointer to storage for the return value
movl 24(%ebp),%ecx
movb %al,0(%ecx)
jmp .Lsc_epilogue
.Lsc_retstruct2b:
# Load %ecx with the pointer to storage for the return value
movl 24(%ebp),%ecx
movw %ax,0(%ecx)
jmp .Lsc_epilogue
.Lsc_retstruct4b:
# Load %ecx with the pointer to storage for the return value
movl 24(%ebp),%ecx
movl %eax,0(%ecx)
jmp .Lsc_epilogue
.Lsc_retstruct:
# Nothing to do!
.Lsc_noretval:
.Lsc_epilogue:
movl %ebp,%esp
popl %ebp
ret
.ffi_call_STDCALL_end:
.LFE2:
# This assumes we are using gas.
.balign 16
.globl _ffi_closure_SYSV
@@ -742,38 +949,6 @@ _ffi_closure_STDCALL:
.LEFDE1:
.LSFDE2:
.long .LEFDE2-.LASFDE2 /* FDE Length */
.LASFDE2:
.long .LASFDE2-.Lframe1 /* FDE CIE offset */
#if defined __PIC__ && defined HAVE_AS_X86_PCREL
.long .LFB2-. /* FDE initial location */
#else
.long .LFB2
#endif
.long .LFE2-.LFB2 /* FDE address range */
#ifdef __PIC__
.byte 0x0 /* .uleb128 0x0; Augmentation size */
#endif
/* DW_CFA_xxx CFI instructions go here. */
.byte 0x4 /* DW_CFA_advance_loc4 */
.long .LCFI2-.LFB2
.byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
.byte 0x8 /* .uleb128 0x8 */
.byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
.byte 0x2 /* .uleb128 0x2 */
.byte 0x4 /* DW_CFA_advance_loc4 */
.long .LCFI3-.LCFI2
.byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
.byte 0x5 /* .uleb128 0x5 */
/* End of DW_CFA_xxx CFI instructions. */
.align 4
.LEFDE2:
.LSFDE3:
.long .LEFDE3-.LASFDE3 /* FDE Length */
.LASFDE3:
@@ -875,3 +1050,6 @@ _ffi_closure_STDCALL:
/* End of DW_CFA_xxx CFI instructions. */
.align 4
.LEFDE5:
#endif /* !_MSC_VER */