Home | History | Annotate | Download | only in x86
      1 /* -----------------------------------------------------------------------
      2    win32.S - Copyright (c) 1996, 1998, 2001, 2002  Red Hat, Inc.
      3 	     Copyright (c) 2001  John Beniton
      4 	     Copyright (c) 2002  Ranjit Mathew
      5 
      6 
      7    X86 Foreign Function Interface
      8 
      9    Permission is hereby granted, free of charge, to any person obtaining
     10    a copy of this software and associated documentation files (the
     11    ``Software''), to deal in the Software without restriction, including
     12    without limitation the rights to use, copy, modify, merge, publish,
     13    distribute, sublicense, and/or sell copies of the Software, and to
     14    permit persons to whom the Software is furnished to do so, subject to
     15    the following conditions:
     16 
     17    The above copyright notice and this permission notice shall be included
     18    in all copies or substantial portions of the Software.
     19 
     20    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
     21    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     22    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     23    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
     24 	ANY CLAIM, DAMAGES OR
     25    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     26    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     27    OTHER DEALINGS IN THE SOFTWARE.
     28    ----------------------------------------------------------------------- */
     29 
     30 #define LIBFFI_ASM
     31 #include <fficonfig.h>
     32 #include <ffi.h>
     33 
     34 .text
     35 
     36 .globl ffi_prep_args
     37 
     38         # This assumes we are using gas.
     39         .balign 16
     40 .globl _ffi_call_SYSV
     41 
     42 _ffi_call_SYSV:
     43         pushl %ebp
     44         movl  %esp,%ebp
     45 
     46         # Make room for all of the new args.
     47         movl  16(%ebp),%ecx
     48         subl  %ecx,%esp
     49 
     50         movl  %esp,%eax
     51 
     52         # Place all of the ffi_prep_args in position
     53         pushl 12(%ebp)
     54         pushl %eax
     55         call  *8(%ebp)
     56 
     57         # Return stack to previous state and call the function
     58         addl  $8,%esp
     59 
     60         # FIXME: Align the stack to a 128-bit boundary to avoid
     61         # potential performance hits.
     62 
     63 	call  *28(%ebp)
     64 
     65         # Remove the space we pushed for the args
     66         movl  16(%ebp),%ecx
     67         addl  %ecx,%esp
     68 
     69         # Load %ecx with the return type code
     70         movl  20(%ebp),%ecx
     71 
     72         # If the return value pointer is NULL, assume no return value.
     73         cmpl  $0,24(%ebp)
     74         jne   retint
     75 
     76         # Even if there is no space for the return value, we are
     77         # obliged to handle floating-point values.
     78         cmpl  $FFI_TYPE_FLOAT,%ecx
     79         jne   noretval
     80         fstp  %st(0)
     81 
     82         jmp   epilogue
     83 
     84 retint:
     85         cmpl  $FFI_TYPE_INT,%ecx
     86         jne   retfloat
     87         # Load %ecx with the pointer to storage for the return value
     88         movl  24(%ebp),%ecx
     89         movl  %eax,0(%ecx)
     90         jmp   epilogue
     91 
     92 retfloat:
     93         cmpl  $FFI_TYPE_FLOAT,%ecx
     94         jne   retdouble
     95          # Load %ecx with the pointer to storage for the return value
     96         movl  24(%ebp),%ecx
     97         fstps (%ecx)
     98         jmp   epilogue
     99 
    100 retdouble:
    101         cmpl  $FFI_TYPE_DOUBLE,%ecx
    102         jne   retlongdouble
    103         # Load %ecx with the pointer to storage for the return value
    104         movl  24(%ebp),%ecx
    105         fstpl (%ecx)
    106         jmp   epilogue
    107 
    108 retlongdouble:
    109         cmpl  $FFI_TYPE_LONGDOUBLE,%ecx
    110         jne   retint64
    111         # Load %ecx with the pointer to storage for the return value
    112         movl  24(%ebp),%ecx
    113         fstpt (%ecx)
    114         jmp   epilogue
    115 
    116 retint64:
    117         cmpl  $FFI_TYPE_SINT64,%ecx
    118         jne   retstruct1b
    119         # Load %ecx with the pointer to storage for the return value
    120         movl  24(%ebp),%ecx
    121         movl  %eax,0(%ecx)
    122         movl  %edx,4(%ecx)
    123 
    124 retstruct1b:
    125         cmpl  $FFI_TYPE_SINT8,%ecx
    126         jne   retstruct2b
    127         # Load %ecx with the pointer to storage for the return value
    128         movl  24(%ebp),%ecx
    129         movb  %al,0(%ecx)
    130         jmp   epilogue
    131 
    132 retstruct2b:
    133         cmpl  $FFI_TYPE_SINT16,%ecx
    134         jne   retstruct
    135         # Load %ecx with the pointer to storage for the return value
    136         movl  24(%ebp),%ecx
    137         movw  %ax,0(%ecx)
    138         jmp   epilogue
    139 
    140 retstruct:
    141         # Nothing to do!
    142 
    143 noretval:
    144 epilogue:
    145         movl %ebp,%esp
    146         popl %ebp
    147         ret
    148 
    149 .ffi_call_SYSV_end:
    150 
    151         # This assumes we are using gas.
    152         .balign 16
    153 .globl _ffi_call_STDCALL
    154 
    155 _ffi_call_STDCALL:
    156         pushl %ebp
    157         movl  %esp,%ebp
    158 
    159         # Make room for all of the new args.
    160         movl  16(%ebp),%ecx
    161         subl  %ecx,%esp
    162 
    163         movl  %esp,%eax
    164 
    165         # Place all of the ffi_prep_args in position
    166         pushl 12(%ebp)
    167         pushl %eax
    168         call  *8(%ebp)
    169 
    170         # Return stack to previous state and call the function
    171         addl  $8,%esp
    172 
    173         # FIXME: Align the stack to a 128-bit boundary to avoid
    174         # potential performance hits.
    175 
    176         call  *28(%ebp)
    177 
    178         # stdcall functions pop arguments off the stack themselves
    179 
    180         # Load %ecx with the return type code
    181         movl  20(%ebp),%ecx
    182 
    183         # If the return value pointer is NULL, assume no return value.
    184         cmpl  $0,24(%ebp)
    185         jne   sc_retint
    186 
    187         # Even if there is no space for the return value, we are
    188         # obliged to handle floating-point values.
    189         cmpl  $FFI_TYPE_FLOAT,%ecx
    190         jne   sc_noretval
    191         fstp  %st(0)
    192 
    193         jmp   sc_epilogue
    194 
    195 sc_retint:
    196         cmpl  $FFI_TYPE_INT,%ecx
    197         jne   sc_retfloat
    198         # Load %ecx with the pointer to storage for the return value
    199         movl  24(%ebp),%ecx
    200         movl  %eax,0(%ecx)
    201         jmp   sc_epilogue
    202 
    203 sc_retfloat:
    204         cmpl  $FFI_TYPE_FLOAT,%ecx
    205         jne   sc_retdouble
    206          # Load %ecx with the pointer to storage for the return value
    207         movl  24(%ebp),%ecx
    208         fstps (%ecx)
    209         jmp   sc_epilogue
    210 
    211 sc_retdouble:
    212         cmpl  $FFI_TYPE_DOUBLE,%ecx
    213         jne   sc_retlongdouble
    214         # Load %ecx with the pointer to storage for the return value
    215         movl  24(%ebp),%ecx
    216         fstpl (%ecx)
    217         jmp   sc_epilogue
    218 
    219 sc_retlongdouble:
    220         cmpl  $FFI_TYPE_LONGDOUBLE,%ecx
    221         jne   sc_retint64
    222         # Load %ecx with the pointer to storage for the return value
    223         movl  24(%ebp),%ecx
    224         fstpt (%ecx)
    225         jmp   sc_epilogue
    226 
    227 sc_retint64:
    228         cmpl  $FFI_TYPE_SINT64,%ecx
    229         jne   sc_retstruct1b
    230         # Load %ecx with the pointer to storage for the return value
    231         movl  24(%ebp),%ecx
    232         movl  %eax,0(%ecx)
    233         movl  %edx,4(%ecx)
    234 
    235 sc_retstruct1b:
    236         cmpl  $FFI_TYPE_SINT8,%ecx
    237         jne   sc_retstruct2b
    238         # Load %ecx with the pointer to storage for the return value
    239         movl  24(%ebp),%ecx
    240         movb  %al,0(%ecx)
    241         jmp   sc_epilogue
    242 
    243 sc_retstruct2b:
    244         cmpl  $FFI_TYPE_SINT16,%ecx
    245         jne   sc_retstruct
    246         # Load %ecx with the pointer to storage for the return value
    247         movl  24(%ebp),%ecx
    248         movw  %ax,0(%ecx)
    249         jmp   sc_epilogue
    250 
    251 sc_retstruct:
    252         # Nothing to do!
    253 
    254 sc_noretval:
    255 sc_epilogue:
    256         movl %ebp,%esp
    257         popl %ebp
    258         ret
    259 
    260 .ffi_call_STDCALL_end:
    261 
    262 	.globl _ffi_closure_STDCALL
    263 _ffi_closure_STDCALL:
    264 	pushl	%ebp
    265 	movl	%esp, %ebp
    266 	subl	$40, %esp
    267 	leal	-24(%ebp), %edx
    268 	movl	%edx, -12(%ebp)	/* resp */
    269 	leal	12(%ebp), %edx  /* account for stub return address on stack */
    270 	movl	%edx, 4(%esp)	/* args */
    271 	leal	-12(%ebp), %edx
    272 	movl	%edx, (%esp)	/* &resp */
    273 	call	_ffi_closure_SYSV_inner
    274 	movl	-12(%ebp), %ecx
    275 	jmp     .Lcls_return_result
    276 .ffi_closure_STDCALL_end:
    277 
    278 	.globl _ffi_closure_SYSV
    279 _ffi_closure_SYSV:
    280 	pushl	%ebp
    281 	movl	%esp, %ebp
    282 	subl	$40, %esp
    283 	leal	-24(%ebp), %edx
    284 	movl	%edx, -12(%ebp)	/* resp */
    285 	leal	8(%ebp), %edx
    286 	movl	%edx, 4(%esp)	/* args = __builtin_dwarf_cfa () */
    287 	leal	-12(%ebp), %edx
    288 	movl	%edx, (%esp)	/* &resp */
    289 	call	_ffi_closure_SYSV_inner
    290 	movl	-12(%ebp), %ecx
    291 .Lcls_return_result:
    292 	cmpl	$FFI_TYPE_INT, %eax
    293 	je	.Lcls_retint
    294 	cmpl	$FFI_TYPE_FLOAT, %eax
    295 	je	.Lcls_retfloat
    296 	cmpl	$FFI_TYPE_DOUBLE, %eax
    297 	je	.Lcls_retdouble
    298 	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
    299 	je	.Lcls_retldouble
    300 	cmpl	$FFI_TYPE_SINT64, %eax
    301 	je	.Lcls_retllong
    302 	cmpl	$FFI_TYPE_SINT8, %eax	/* 1-byte struct */
    303 	je	.Lcls_retstruct1
    304 	cmpl	$FFI_TYPE_SINT16, %eax	/* 2-bytes struct */
    305 	je	.Lcls_retstruct2
    306 .Lcls_epilogue:
    307 	movl	%ebp, %esp
    308 	popl	%ebp
    309 	ret
    310 .Lcls_retint:
    311 	movl	(%ecx), %eax
    312 	jmp	.Lcls_epilogue
    313 .Lcls_retfloat:
    314 	flds	(%ecx)
    315 	jmp	.Lcls_epilogue
    316 .Lcls_retdouble:
    317 	fldl	(%ecx)
    318 	jmp	.Lcls_epilogue
    319 .Lcls_retldouble:
    320 	fldt	(%ecx)
    321 	jmp	.Lcls_epilogue
    322 .Lcls_retllong:
    323 	movl	(%ecx), %eax
    324 	movl	4(%ecx), %edx
    325 	jmp	.Lcls_epilogue
    326 .Lcls_retstruct1:
    327 	movsbl	(%ecx), %eax
    328 	jmp	.Lcls_epilogue
    329 .Lcls_retstruct2:
    330 	movswl	(%ecx), %eax
    331 	jmp	.Lcls_epilogue
    332 .ffi_closure_SYSV_end:
    333 
    334 #if !FFI_NO_RAW_API
    335 
    336 #define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
    337 #define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
    338 #define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
    339 #define CIF_FLAGS_OFFSET 20
    340 
    341 	.balign	16
    342 	.globl _ffi_closure_raw_SYSV
    343 _ffi_closure_raw_SYSV:
    344 	pushl	%ebp
    345 	movl	%esp, %ebp
    346 	pushl	%esi
    347 	subl	$36, %esp
    348 	movl	RAW_CLOSURE_CIF_OFFSET(%eax), %esi	 /* closure->cif */
    349 	movl	RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
    350 	movl	%edx, 12(%esp)	/* user_data */
    351 	leal	8(%ebp), %edx	/* __builtin_dwarf_cfa () */
    352 	movl	%edx, 8(%esp)	/* raw_args */
    353 	leal	-24(%ebp), %edx
    354 	movl	%edx, 4(%esp)	/* &res */
    355 	movl	%esi, (%esp)	/* cif */
    356 	call	*RAW_CLOSURE_FUN_OFFSET(%eax)		 /* closure->fun */
    357 	movl	CIF_FLAGS_OFFSET(%esi), %eax		 /* rtype */
    358 	cmpl	$FFI_TYPE_INT, %eax
    359 	je	.Lrcls_retint
    360 	cmpl	$FFI_TYPE_FLOAT, %eax
    361 	je	.Lrcls_retfloat
    362 	cmpl	$FFI_TYPE_DOUBLE, %eax
    363 	je	.Lrcls_retdouble
    364 	cmpl	$FFI_TYPE_LONGDOUBLE, %eax
    365 	je	.Lrcls_retldouble
    366 	cmpl	$FFI_TYPE_SINT64, %eax
    367 	je	.Lrcls_retllong
    368 .Lrcls_epilogue:
    369 	addl	$36, %esp
    370 	popl	%esi
    371 	popl	%ebp
    372 	ret
    373 .Lrcls_retint:
    374 	movl	-24(%ebp), %eax
    375 	jmp	.Lrcls_epilogue
    376 .Lrcls_retfloat:
    377 	flds	-24(%ebp)
    378 	jmp	.Lrcls_epilogue
    379 .Lrcls_retdouble:
    380 	fldl	-24(%ebp)
    381 	jmp	.Lrcls_epilogue
    382 .Lrcls_retldouble:
    383 	fldt	-24(%ebp)
    384 	jmp	.Lrcls_epilogue
    385 .Lrcls_retllong:
    386 	movl	-24(%ebp), %eax
    387 	movl	-20(%ebp), %edx
    388 	jmp	.Lrcls_epilogue
    389 .ffi_closure_raw_SYSV_end:
    390 
    391 #endif
    392