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 84retint: 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 92retfloat: 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 100retdouble: 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 108retlongdouble: 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 116retint64: 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 124retstruct1b: 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 132retstruct2b: 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 140retstruct: 141 # Nothing to do! 142 143noretval: 144epilogue: 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 195sc_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 203sc_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 211sc_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 219sc_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 227sc_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 235sc_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 243sc_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 251sc_retstruct: 252 # Nothing to do! 253 254sc_noretval: 255sc_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