diff options
Diffstat (limited to 'src/x86/win32.S')
-rw-r--r-- | src/x86/win32.S | 560 |
1 files changed, 369 insertions, 191 deletions
diff --git a/src/x86/win32.S b/src/x86/win32.S index 7489dab..ac1ed6f 100644 --- a/src/x86/win32.S +++ b/src/x86/win32.S @@ -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,164 +541,11 @@ _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 .def _ffi_closure_SYSV; .scl 2; .type 32; .endef _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 */ + |