libffi merge
[gcc.git] / libffi / src / x86 / win32.S
1 /* -----------------------------------------------------------------------
2 win32.S - Copyright (c) 1996, 1998, 2001, 2002, 2009 Red Hat, Inc.
3 Copyright (c) 2001 John Beniton
4 Copyright (c) 2002 Ranjit Mathew
5 Copyright (c) 2009 Daniel Witte
6
7
8 X86 Foreign Function Interface
9
10 Permission is hereby granted, free of charge, to any person obtaining
11 a copy of this software and associated documentation files (the
12 ``Software''), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sublicense, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice shall be included
19 in all copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 DEALINGS IN THE SOFTWARE.
29 -----------------------------------------------------------------------
30 */
31
32 #define LIBFFI_ASM
33 #include <fficonfig.h>
34 #include <ffi.h>
35
36 #ifdef _MSC_VER
37
38 .386
39 .MODEL FLAT, C
40
41 EXTRN ffi_closure_SYSV_inner:NEAR
42
43 _TEXT SEGMENT
44
45 ffi_call_win32 PROC NEAR,
46 ffi_prep_args : NEAR PTR DWORD,
47 ecif : NEAR PTR DWORD,
48 cif_abi : DWORD,
49 cif_bytes : DWORD,
50 cif_flags : DWORD,
51 rvalue : NEAR PTR DWORD,
52 fn : NEAR PTR DWORD
53
54 ;; Make room for all of the new args.
55 mov ecx, cif_bytes
56 sub esp, ecx
57
58 mov eax, esp
59
60 ;; Place all of the ffi_prep_args in position
61 push ecif
62 push eax
63 call ffi_prep_args
64
65 ;; Return stack to previous state and call the function
66 add esp, 8
67
68 ;; Handle thiscall and fastcall
69 cmp cif_abi, 3 ;; FFI_THISCALL
70 jz do_thiscall
71 cmp cif_abi, 4 ;; FFI_FASTCALL
72 jnz do_stdcall
73 mov ecx, DWORD PTR [esp]
74 mov edx, DWORD PTR [esp+4]
75 add esp, 8
76 jmp do_stdcall
77 do_thiscall:
78 mov ecx, DWORD PTR [esp]
79 add esp, 4
80 do_stdcall:
81 call fn
82
83 ;; cdecl: we restore esp in the epilogue, so there's no need to
84 ;; remove the space we pushed for the args.
85 ;; stdcall: the callee has already cleaned the stack.
86
87 ;; Load ecx with the return type code
88 mov ecx, cif_flags
89
90 ;; If the return value pointer is NULL, assume no return value.
91 cmp rvalue, 0
92 jne ca_jumptable
93
94 ;; Even if there is no space for the return value, we are
95 ;; obliged to handle floating-point values.
96 cmp ecx, FFI_TYPE_FLOAT
97 jne ca_epilogue
98 fstp st(0)
99
100 jmp ca_epilogue
101
102 ca_jumptable:
103 jmp [ca_jumpdata + 4 * ecx]
104 ca_jumpdata:
105 ;; Do not insert anything here between label and jump table.
106 dd offset ca_epilogue ;; FFI_TYPE_VOID
107 dd offset ca_retint ;; FFI_TYPE_INT
108 dd offset ca_retfloat ;; FFI_TYPE_FLOAT
109 dd offset ca_retdouble ;; FFI_TYPE_DOUBLE
110 dd offset ca_retlongdouble ;; FFI_TYPE_LONGDOUBLE
111 dd offset ca_retuint8 ;; FFI_TYPE_UINT8
112 dd offset ca_retsint8 ;; FFI_TYPE_SINT8
113 dd offset ca_retuint16 ;; FFI_TYPE_UINT16
114 dd offset ca_retsint16 ;; FFI_TYPE_SINT16
115 dd offset ca_retint ;; FFI_TYPE_UINT32
116 dd offset ca_retint ;; FFI_TYPE_SINT32
117 dd offset ca_retint64 ;; FFI_TYPE_UINT64
118 dd offset ca_retint64 ;; FFI_TYPE_SINT64
119 dd offset ca_epilogue ;; FFI_TYPE_STRUCT
120 dd offset ca_retint ;; FFI_TYPE_POINTER
121 dd offset ca_retstruct1b ;; FFI_TYPE_SMALL_STRUCT_1B
122 dd offset ca_retstruct2b ;; FFI_TYPE_SMALL_STRUCT_2B
123 dd offset ca_retint ;; FFI_TYPE_SMALL_STRUCT_4B
124 dd offset ca_epilogue ;; FFI_TYPE_MS_STRUCT
125
126 /* Sign/zero extend as appropriate. */
127 ca_retuint8:
128 movzx eax, al
129 jmp ca_retint
130
131 ca_retsint8:
132 movsx eax, al
133 jmp ca_retint
134
135 ca_retuint16:
136 movzx eax, ax
137 jmp ca_retint
138
139 ca_retsint16:
140 movsx eax, ax
141 jmp ca_retint
142
143 ca_retint:
144 ;; Load %ecx with the pointer to storage for the return value
145 mov ecx, rvalue
146 mov [ecx + 0], eax
147 jmp ca_epilogue
148
149 ca_retint64:
150 ;; Load %ecx with the pointer to storage for the return value
151 mov ecx, rvalue
152 mov [ecx + 0], eax
153 mov [ecx + 4], edx
154 jmp ca_epilogue
155
156 ca_retfloat:
157 ;; Load %ecx with the pointer to storage for the return value
158 mov ecx, rvalue
159 fstp DWORD PTR [ecx]
160 jmp ca_epilogue
161
162 ca_retdouble:
163 ;; Load %ecx with the pointer to storage for the return value
164 mov ecx, rvalue
165 fstp QWORD PTR [ecx]
166 jmp ca_epilogue
167
168 ca_retlongdouble:
169 ;; Load %ecx with the pointer to storage for the return value
170 mov ecx, rvalue
171 fstp TBYTE PTR [ecx]
172 jmp ca_epilogue
173
174 ca_retstruct1b:
175 ;; Load %ecx with the pointer to storage for the return value
176 mov ecx, rvalue
177 mov [ecx + 0], al
178 jmp ca_epilogue
179
180 ca_retstruct2b:
181 ;; Load %ecx with the pointer to storage for the return value
182 mov ecx, rvalue
183 mov [ecx + 0], ax
184 jmp ca_epilogue
185
186 ca_epilogue:
187 ;; Epilogue code is autogenerated.
188 ret
189 ffi_call_win32 ENDP
190
191 ffi_closure_THISCALL PROC NEAR FORCEFRAME
192 sub esp, 40
193 lea edx, [ebp -24]
194 mov [ebp - 12], edx /* resp */
195 lea edx, [ebp + 12] /* account for stub return address on stack */
196 jmp stub
197 ffi_closure_THISCALL ENDP
198
199 ffi_closure_SYSV PROC NEAR FORCEFRAME
200 ;; the ffi_closure ctx is passed in eax by the trampoline.
201
202 sub esp, 40
203 lea edx, [ebp - 24]
204 mov [ebp - 12], edx ;; resp
205 lea edx, [ebp + 8]
206 stub::
207 mov [esp + 8], edx ;; args
208 lea edx, [ebp - 12]
209 mov [esp + 4], edx ;; &resp
210 mov [esp], eax ;; closure
211 call ffi_closure_SYSV_inner
212 mov ecx, [ebp - 12]
213
214 cs_jumptable:
215 jmp [cs_jumpdata + 4 * eax]
216 cs_jumpdata:
217 ;; Do not insert anything here between the label and jump table.
218 dd offset cs_epilogue ;; FFI_TYPE_VOID
219 dd offset cs_retint ;; FFI_TYPE_INT
220 dd offset cs_retfloat ;; FFI_TYPE_FLOAT
221 dd offset cs_retdouble ;; FFI_TYPE_DOUBLE
222 dd offset cs_retlongdouble ;; FFI_TYPE_LONGDOUBLE
223 dd offset cs_retuint8 ;; FFI_TYPE_UINT8
224 dd offset cs_retsint8 ;; FFI_TYPE_SINT8
225 dd offset cs_retuint16 ;; FFI_TYPE_UINT16
226 dd offset cs_retsint16 ;; FFI_TYPE_SINT16
227 dd offset cs_retint ;; FFI_TYPE_UINT32
228 dd offset cs_retint ;; FFI_TYPE_SINT32
229 dd offset cs_retint64 ;; FFI_TYPE_UINT64
230 dd offset cs_retint64 ;; FFI_TYPE_SINT64
231 dd offset cs_retstruct ;; FFI_TYPE_STRUCT
232 dd offset cs_retint ;; FFI_TYPE_POINTER
233 dd offset cs_retsint8 ;; FFI_TYPE_SMALL_STRUCT_1B
234 dd offset cs_retsint16 ;; FFI_TYPE_SMALL_STRUCT_2B
235 dd offset cs_retint ;; FFI_TYPE_SMALL_STRUCT_4B
236 dd offset cs_retmsstruct ;; FFI_TYPE_MS_STRUCT
237
238 cs_retuint8:
239 movzx eax, BYTE PTR [ecx]
240 jmp cs_epilogue
241
242 cs_retsint8:
243 movsx eax, BYTE PTR [ecx]
244 jmp cs_epilogue
245
246 cs_retuint16:
247 movzx eax, WORD PTR [ecx]
248 jmp cs_epilogue
249
250 cs_retsint16:
251 movsx eax, WORD PTR [ecx]
252 jmp cs_epilogue
253
254 cs_retint:
255 mov eax, [ecx]
256 jmp cs_epilogue
257
258 cs_retint64:
259 mov eax, [ecx + 0]
260 mov edx, [ecx + 4]
261 jmp cs_epilogue
262
263 cs_retfloat:
264 fld DWORD PTR [ecx]
265 jmp cs_epilogue
266
267 cs_retdouble:
268 fld QWORD PTR [ecx]
269 jmp cs_epilogue
270
271 cs_retlongdouble:
272 fld TBYTE PTR [ecx]
273 jmp cs_epilogue
274
275 cs_retstruct:
276 ;; Caller expects us to pop struct return value pointer hidden arg.
277 ;; Epilogue code is autogenerated.
278 ret 4
279
280 cs_retmsstruct:
281 ;; Caller expects us to return a pointer to the real return value.
282 mov eax, ecx
283 ;; Caller doesn't expects us to pop struct return value pointer hidden arg.
284 jmp cs_epilogue
285
286 cs_epilogue:
287 ;; Epilogue code is autogenerated.
288 ret
289 ffi_closure_SYSV ENDP
290
291 #if !FFI_NO_RAW_API
292
293 #define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) AND NOT 3)
294 #define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
295 #define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
296 #define CIF_FLAGS_OFFSET 20
297
298 ffi_closure_raw_THISCALL PROC NEAR USES esi FORCEFRAME
299 sub esp, 36
300 mov esi, [eax + RAW_CLOSURE_CIF_OFFSET] ;; closure->cif
301 mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data
302 mov [esp + 12], edx
303 lea edx, [ebp + 12]
304 jmp stubraw
305 ffi_closure_raw_THISCALL ENDP
306
307 ffi_closure_raw_SYSV PROC NEAR USES esi FORCEFRAME
308 ;; the ffi_closure ctx is passed in eax by the trampoline.
309
310 sub esp, 40
311 mov esi, [eax + RAW_CLOSURE_CIF_OFFSET] ;; closure->cif
312 mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data
313 mov [esp + 12], edx ;; user_data
314 lea edx, [ebp + 8]
315 stubraw::
316 mov [esp + 8], edx ;; raw_args
317 lea edx, [ebp - 24]
318 mov [esp + 4], edx ;; &res
319 mov [esp], esi ;; cif
320 call DWORD PTR [eax + RAW_CLOSURE_FUN_OFFSET] ;; closure->fun
321 mov eax, [esi + CIF_FLAGS_OFFSET] ;; cif->flags
322 lea ecx, [ebp - 24]
323
324 cr_jumptable:
325 jmp [cr_jumpdata + 4 * eax]
326 cr_jumpdata:
327 ;; Do not insert anything here between the label and jump table.
328 dd offset cr_epilogue ;; FFI_TYPE_VOID
329 dd offset cr_retint ;; FFI_TYPE_INT
330 dd offset cr_retfloat ;; FFI_TYPE_FLOAT
331 dd offset cr_retdouble ;; FFI_TYPE_DOUBLE
332 dd offset cr_retlongdouble ;; FFI_TYPE_LONGDOUBLE
333 dd offset cr_retuint8 ;; FFI_TYPE_UINT8
334 dd offset cr_retsint8 ;; FFI_TYPE_SINT8
335 dd offset cr_retuint16 ;; FFI_TYPE_UINT16
336 dd offset cr_retsint16 ;; FFI_TYPE_SINT16
337 dd offset cr_retint ;; FFI_TYPE_UINT32
338 dd offset cr_retint ;; FFI_TYPE_SINT32
339 dd offset cr_retint64 ;; FFI_TYPE_UINT64
340 dd offset cr_retint64 ;; FFI_TYPE_SINT64
341 dd offset cr_epilogue ;; FFI_TYPE_STRUCT
342 dd offset cr_retint ;; FFI_TYPE_POINTER
343 dd offset cr_retsint8 ;; FFI_TYPE_SMALL_STRUCT_1B
344 dd offset cr_retsint16 ;; FFI_TYPE_SMALL_STRUCT_2B
345 dd offset cr_retint ;; FFI_TYPE_SMALL_STRUCT_4B
346 dd offset cr_epilogue ;; FFI_TYPE_MS_STRUCT
347
348 cr_retuint8:
349 movzx eax, BYTE PTR [ecx]
350 jmp cr_epilogue
351
352 cr_retsint8:
353 movsx eax, BYTE PTR [ecx]
354 jmp cr_epilogue
355
356 cr_retuint16:
357 movzx eax, WORD PTR [ecx]
358 jmp cr_epilogue
359
360 cr_retsint16:
361 movsx eax, WORD PTR [ecx]
362 jmp cr_epilogue
363
364 cr_retint:
365 mov eax, [ecx]
366 jmp cr_epilogue
367
368 cr_retint64:
369 mov eax, [ecx + 0]
370 mov edx, [ecx + 4]
371 jmp cr_epilogue
372
373 cr_retfloat:
374 fld DWORD PTR [ecx]
375 jmp cr_epilogue
376
377 cr_retdouble:
378 fld QWORD PTR [ecx]
379 jmp cr_epilogue
380
381 cr_retlongdouble:
382 fld TBYTE PTR [ecx]
383 jmp cr_epilogue
384
385 cr_epilogue:
386 ;; Epilogue code is autogenerated.
387 ret
388 ffi_closure_raw_SYSV ENDP
389
390 #endif /* !FFI_NO_RAW_API */
391
392 ffi_closure_STDCALL PROC NEAR FORCEFRAME
393 ;; the ffi_closure ctx is passed in eax by the trampoline.
394
395 sub esp, 40
396 lea edx, [ebp - 24]
397 mov [ebp - 12], edx ;; resp
398 lea edx, [ebp + 12] ;; account for stub return address on stack
399 mov [esp + 8], edx ;; args
400 lea edx, [ebp - 12]
401 mov [esp + 4], edx ;; &resp
402 mov [esp], eax ;; closure
403 call ffi_closure_SYSV_inner
404 mov ecx, [ebp - 12]
405
406 cd_jumptable:
407 jmp [cd_jumpdata + 4 * eax]
408 cd_jumpdata:
409 ;; Do not insert anything here between the label and jump table.
410 dd offset cd_epilogue ;; FFI_TYPE_VOID
411 dd offset cd_retint ;; FFI_TYPE_INT
412 dd offset cd_retfloat ;; FFI_TYPE_FLOAT
413 dd offset cd_retdouble ;; FFI_TYPE_DOUBLE
414 dd offset cd_retlongdouble ;; FFI_TYPE_LONGDOUBLE
415 dd offset cd_retuint8 ;; FFI_TYPE_UINT8
416 dd offset cd_retsint8 ;; FFI_TYPE_SINT8
417 dd offset cd_retuint16 ;; FFI_TYPE_UINT16
418 dd offset cd_retsint16 ;; FFI_TYPE_SINT16
419 dd offset cd_retint ;; FFI_TYPE_UINT32
420 dd offset cd_retint ;; FFI_TYPE_SINT32
421 dd offset cd_retint64 ;; FFI_TYPE_UINT64
422 dd offset cd_retint64 ;; FFI_TYPE_SINT64
423 dd offset cd_epilogue ;; FFI_TYPE_STRUCT
424 dd offset cd_retint ;; FFI_TYPE_POINTER
425 dd offset cd_retsint8 ;; FFI_TYPE_SMALL_STRUCT_1B
426 dd offset cd_retsint16 ;; FFI_TYPE_SMALL_STRUCT_2B
427 dd offset cd_retint ;; FFI_TYPE_SMALL_STRUCT_4B
428
429 cd_retuint8:
430 movzx eax, BYTE PTR [ecx]
431 jmp cd_epilogue
432
433 cd_retsint8:
434 movsx eax, BYTE PTR [ecx]
435 jmp cd_epilogue
436
437 cd_retuint16:
438 movzx eax, WORD PTR [ecx]
439 jmp cd_epilogue
440
441 cd_retsint16:
442 movsx eax, WORD PTR [ecx]
443 jmp cd_epilogue
444
445 cd_retint:
446 mov eax, [ecx]
447 jmp cd_epilogue
448
449 cd_retint64:
450 mov eax, [ecx + 0]
451 mov edx, [ecx + 4]
452 jmp cd_epilogue
453
454 cd_retfloat:
455 fld DWORD PTR [ecx]
456 jmp cd_epilogue
457
458 cd_retdouble:
459 fld QWORD PTR [ecx]
460 jmp cd_epilogue
461
462 cd_retlongdouble:
463 fld TBYTE PTR [ecx]
464 jmp cd_epilogue
465
466 cd_epilogue:
467 ;; Epilogue code is autogenerated.
468 ret
469 ffi_closure_STDCALL ENDP
470
471 _TEXT ENDS
472 END
473
474 #else
475
476 .text
477
478 # This assumes we are using gas.
479 .balign 16
480 .globl _ffi_call_win32
481 #ifndef __OS2__
482 .def _ffi_call_win32; .scl 2; .type 32; .endef
483 #endif
484 _ffi_call_win32:
485 .LFB1:
486 pushl %ebp
487 .LCFI0:
488 movl %esp,%ebp
489 .LCFI1:
490 # Make room for all of the new args.
491 movl 20(%ebp),%ecx
492 subl %ecx,%esp
493
494 movl %esp,%eax
495
496 # Place all of the ffi_prep_args in position
497 pushl 12(%ebp)
498 pushl %eax
499 call *8(%ebp)
500
501 # Return stack to previous state and call the function
502 addl $8,%esp
503
504 # Handle fastcall and thiscall
505 cmpl $3, 16(%ebp) # FFI_THISCALL
506 jz .do_thiscall
507 cmpl $4, 16(%ebp) # FFI_FASTCALL
508 jnz .do_fncall
509 movl (%esp), %ecx
510 movl 4(%esp), %edx
511 addl $8, %esp
512 jmp .do_fncall
513 .do_thiscall:
514 movl (%esp), %ecx
515 addl $4, %esp
516
517 .do_fncall:
518
519 # FIXME: Align the stack to a 128-bit boundary to avoid
520 # potential performance hits.
521
522 call *32(%ebp)
523
524 # stdcall functions pop arguments off the stack themselves
525
526 # Load %ecx with the return type code
527 movl 24(%ebp),%ecx
528
529 # If the return value pointer is NULL, assume no return value.
530 cmpl $0,28(%ebp)
531 jne 0f
532
533 # Even if there is no space for the return value, we are
534 # obliged to handle floating-point values.
535 cmpl $FFI_TYPE_FLOAT,%ecx
536 jne .Lnoretval
537 fstp %st(0)
538
539 jmp .Lepilogue
540
541 0:
542 call 1f
543 # Do not insert anything here between the call and the jump table.
544 .Lstore_table:
545 .long .Lnoretval /* FFI_TYPE_VOID */
546 .long .Lretint /* FFI_TYPE_INT */
547 .long .Lretfloat /* FFI_TYPE_FLOAT */
548 .long .Lretdouble /* FFI_TYPE_DOUBLE */
549 .long .Lretlongdouble /* FFI_TYPE_LONGDOUBLE */
550 .long .Lretuint8 /* FFI_TYPE_UINT8 */
551 .long .Lretsint8 /* FFI_TYPE_SINT8 */
552 .long .Lretuint16 /* FFI_TYPE_UINT16 */
553 .long .Lretsint16 /* FFI_TYPE_SINT16 */
554 .long .Lretint /* FFI_TYPE_UINT32 */
555 .long .Lretint /* FFI_TYPE_SINT32 */
556 .long .Lretint64 /* FFI_TYPE_UINT64 */
557 .long .Lretint64 /* FFI_TYPE_SINT64 */
558 .long .Lretstruct /* FFI_TYPE_STRUCT */
559 .long .Lretint /* FFI_TYPE_POINTER */
560 .long .Lretstruct1b /* FFI_TYPE_SMALL_STRUCT_1B */
561 .long .Lretstruct2b /* FFI_TYPE_SMALL_STRUCT_2B */
562 .long .Lretstruct4b /* FFI_TYPE_SMALL_STRUCT_4B */
563 .long .Lretstruct /* FFI_TYPE_MS_STRUCT */
564 1:
565 add %ecx, %ecx
566 add %ecx, %ecx
567 add (%esp),%ecx
568 add $4, %esp
569 jmp *(%ecx)
570
571 /* Sign/zero extend as appropriate. */
572 .Lretsint8:
573 movsbl %al, %eax
574 jmp .Lretint
575
576 .Lretsint16:
577 movswl %ax, %eax
578 jmp .Lretint
579
580 .Lretuint8:
581 movzbl %al, %eax
582 jmp .Lretint
583
584 .Lretuint16:
585 movzwl %ax, %eax
586 jmp .Lretint
587
588 .Lretint:
589 # Load %ecx with the pointer to storage for the return value
590 movl 28(%ebp),%ecx
591 movl %eax,0(%ecx)
592 jmp .Lepilogue
593
594 .Lretfloat:
595 # Load %ecx with the pointer to storage for the return value
596 movl 28(%ebp),%ecx
597 fstps (%ecx)
598 jmp .Lepilogue
599
600 .Lretdouble:
601 # Load %ecx with the pointer to storage for the return value
602 movl 28(%ebp),%ecx
603 fstpl (%ecx)
604 jmp .Lepilogue
605
606 .Lretlongdouble:
607 # Load %ecx with the pointer to storage for the return value
608 movl 28(%ebp),%ecx
609 fstpt (%ecx)
610 jmp .Lepilogue
611
612 .Lretint64:
613 # Load %ecx with the pointer to storage for the return value
614 movl 28(%ebp),%ecx
615 movl %eax,0(%ecx)
616 movl %edx,4(%ecx)
617 jmp .Lepilogue
618
619 .Lretstruct1b:
620 # Load %ecx with the pointer to storage for the return value
621 movl 28(%ebp),%ecx
622 movb %al,0(%ecx)
623 jmp .Lepilogue
624
625 .Lretstruct2b:
626 # Load %ecx with the pointer to storage for the return value
627 movl 28(%ebp),%ecx
628 movw %ax,0(%ecx)
629 jmp .Lepilogue
630
631 .Lretstruct4b:
632 # Load %ecx with the pointer to storage for the return value
633 movl 28(%ebp),%ecx
634 movl %eax,0(%ecx)
635 jmp .Lepilogue
636
637 .Lretstruct:
638 # Nothing to do!
639
640 .Lnoretval:
641 .Lepilogue:
642 movl %ebp,%esp
643 popl %ebp
644 ret
645 .ffi_call_win32_end:
646 .balign 16
647 .globl _ffi_closure_THISCALL
648 #ifndef __OS2__
649 .def _ffi_closure_THISCALL; .scl 2; .type 32; .endef
650 #endif
651 _ffi_closure_THISCALL:
652 pushl %ebp
653 movl %esp, %ebp
654 subl $40, %esp
655 leal -24(%ebp), %edx
656 movl %edx, -12(%ebp) /* resp */
657 leal 12(%ebp), %edx /* account for stub return address on stack */
658 jmp .stub
659 .LFE1:
660
661 # This assumes we are using gas.
662 .balign 16
663 .globl _ffi_closure_SYSV
664 #ifndef __OS2__
665 .def _ffi_closure_SYSV; .scl 2; .type 32; .endef
666 #endif
667 _ffi_closure_SYSV:
668 .LFB3:
669 pushl %ebp
670 .LCFI4:
671 movl %esp, %ebp
672 .LCFI5:
673 subl $40, %esp
674 leal -24(%ebp), %edx
675 movl %edx, -12(%ebp) /* resp */
676 leal 8(%ebp), %edx
677 .stub:
678 movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */
679 leal -12(%ebp), %edx
680 movl %edx, (%esp) /* &resp */
681 call _ffi_closure_SYSV_inner
682 movl -12(%ebp), %ecx
683
684 0:
685 call 1f
686 # Do not insert anything here between the call and the jump table.
687 .Lcls_store_table:
688 .long .Lcls_noretval /* FFI_TYPE_VOID */
689 .long .Lcls_retint /* FFI_TYPE_INT */
690 .long .Lcls_retfloat /* FFI_TYPE_FLOAT */
691 .long .Lcls_retdouble /* FFI_TYPE_DOUBLE */
692 .long .Lcls_retldouble /* FFI_TYPE_LONGDOUBLE */
693 .long .Lcls_retuint8 /* FFI_TYPE_UINT8 */
694 .long .Lcls_retsint8 /* FFI_TYPE_SINT8 */
695 .long .Lcls_retuint16 /* FFI_TYPE_UINT16 */
696 .long .Lcls_retsint16 /* FFI_TYPE_SINT16 */
697 .long .Lcls_retint /* FFI_TYPE_UINT32 */
698 .long .Lcls_retint /* FFI_TYPE_SINT32 */
699 .long .Lcls_retllong /* FFI_TYPE_UINT64 */
700 .long .Lcls_retllong /* FFI_TYPE_SINT64 */
701 .long .Lcls_retstruct /* FFI_TYPE_STRUCT */
702 .long .Lcls_retint /* FFI_TYPE_POINTER */
703 .long .Lcls_retstruct1 /* FFI_TYPE_SMALL_STRUCT_1B */
704 .long .Lcls_retstruct2 /* FFI_TYPE_SMALL_STRUCT_2B */
705 .long .Lcls_retstruct4 /* FFI_TYPE_SMALL_STRUCT_4B */
706 .long .Lcls_retmsstruct /* FFI_TYPE_MS_STRUCT */
707
708 1:
709 add %eax, %eax
710 add %eax, %eax
711 add (%esp),%eax
712 add $4, %esp
713 jmp *(%eax)
714
715 /* Sign/zero extend as appropriate. */
716 .Lcls_retsint8:
717 movsbl (%ecx), %eax
718 jmp .Lcls_epilogue
719
720 .Lcls_retsint16:
721 movswl (%ecx), %eax
722 jmp .Lcls_epilogue
723
724 .Lcls_retuint8:
725 movzbl (%ecx), %eax
726 jmp .Lcls_epilogue
727
728 .Lcls_retuint16:
729 movzwl (%ecx), %eax
730 jmp .Lcls_epilogue
731
732 .Lcls_retint:
733 movl (%ecx), %eax
734 jmp .Lcls_epilogue
735
736 .Lcls_retfloat:
737 flds (%ecx)
738 jmp .Lcls_epilogue
739
740 .Lcls_retdouble:
741 fldl (%ecx)
742 jmp .Lcls_epilogue
743
744 .Lcls_retldouble:
745 fldt (%ecx)
746 jmp .Lcls_epilogue
747
748 .Lcls_retllong:
749 movl (%ecx), %eax
750 movl 4(%ecx), %edx
751 jmp .Lcls_epilogue
752
753 .Lcls_retstruct1:
754 movsbl (%ecx), %eax
755 jmp .Lcls_epilogue
756
757 .Lcls_retstruct2:
758 movswl (%ecx), %eax
759 jmp .Lcls_epilogue
760
761 .Lcls_retstruct4:
762 movl (%ecx), %eax
763 jmp .Lcls_epilogue
764
765 .Lcls_retstruct:
766 # Caller expects us to pop struct return value pointer hidden arg.
767 movl %ebp, %esp
768 popl %ebp
769 ret $0x4
770
771 .Lcls_retmsstruct:
772 # Caller expects us to return a pointer to the real return value.
773 mov %ecx, %eax
774 # Caller doesn't expects us to pop struct return value pointer hidden arg.
775 jmp .Lcls_epilogue
776
777 .Lcls_noretval:
778 .Lcls_epilogue:
779 movl %ebp, %esp
780 popl %ebp
781 ret
782 .ffi_closure_SYSV_end:
783 .LFE3:
784
785 #if !FFI_NO_RAW_API
786
787 #define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
788 #define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
789 #define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
790 #define CIF_FLAGS_OFFSET 20
791 .balign 16
792 .globl _ffi_closure_raw_THISCALL
793 #ifndef __OS2__
794 .def _ffi_closure_raw_THISCALL; .scl 2; .type 32; .endef
795 #endif
796 _ffi_closure_raw_THISCALL:
797 pushl %ebp
798 movl %esp, %ebp
799 pushl %esi
800 subl $36, %esp
801 movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */
802 movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
803 movl %edx, 12(%esp) /* user_data */
804 leal 12(%ebp), %edx /* __builtin_dwarf_cfa () */
805 jmp .stubraw
806 # This assumes we are using gas.
807 .balign 16
808 .globl _ffi_closure_raw_SYSV
809 #ifndef __OS2__
810 .def _ffi_closure_raw_SYSV; .scl 2; .type 32; .endef
811 #endif
812 _ffi_closure_raw_SYSV:
813 .LFB4:
814 pushl %ebp
815 .LCFI6:
816 movl %esp, %ebp
817 .LCFI7:
818 pushl %esi
819 .LCFI8:
820 subl $36, %esp
821 movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */
822 movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
823 movl %edx, 12(%esp) /* user_data */
824 leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */
825 .stubraw:
826 movl %edx, 8(%esp) /* raw_args */
827 leal -24(%ebp), %edx
828 movl %edx, 4(%esp) /* &res */
829 movl %esi, (%esp) /* cif */
830 call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */
831 movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */
832 0:
833 call 1f
834 # Do not insert anything here between the call and the jump table.
835 .Lrcls_store_table:
836 .long .Lrcls_noretval /* FFI_TYPE_VOID */
837 .long .Lrcls_retint /* FFI_TYPE_INT */
838 .long .Lrcls_retfloat /* FFI_TYPE_FLOAT */
839 .long .Lrcls_retdouble /* FFI_TYPE_DOUBLE */
840 .long .Lrcls_retldouble /* FFI_TYPE_LONGDOUBLE */
841 .long .Lrcls_retuint8 /* FFI_TYPE_UINT8 */
842 .long .Lrcls_retsint8 /* FFI_TYPE_SINT8 */
843 .long .Lrcls_retuint16 /* FFI_TYPE_UINT16 */
844 .long .Lrcls_retsint16 /* FFI_TYPE_SINT16 */
845 .long .Lrcls_retint /* FFI_TYPE_UINT32 */
846 .long .Lrcls_retint /* FFI_TYPE_SINT32 */
847 .long .Lrcls_retllong /* FFI_TYPE_UINT64 */
848 .long .Lrcls_retllong /* FFI_TYPE_SINT64 */
849 .long .Lrcls_retstruct /* FFI_TYPE_STRUCT */
850 .long .Lrcls_retint /* FFI_TYPE_POINTER */
851 .long .Lrcls_retstruct1 /* FFI_TYPE_SMALL_STRUCT_1B */
852 .long .Lrcls_retstruct2 /* FFI_TYPE_SMALL_STRUCT_2B */
853 .long .Lrcls_retstruct4 /* FFI_TYPE_SMALL_STRUCT_4B */
854 .long .Lrcls_retstruct /* FFI_TYPE_MS_STRUCT */
855 1:
856 add %eax, %eax
857 add %eax, %eax
858 add (%esp),%eax
859 add $4, %esp
860 jmp *(%eax)
861
862 /* Sign/zero extend as appropriate. */
863 .Lrcls_retsint8:
864 movsbl -24(%ebp), %eax
865 jmp .Lrcls_epilogue
866
867 .Lrcls_retsint16:
868 movswl -24(%ebp), %eax
869 jmp .Lrcls_epilogue
870
871 .Lrcls_retuint8:
872 movzbl -24(%ebp), %eax
873 jmp .Lrcls_epilogue
874
875 .Lrcls_retuint16:
876 movzwl -24(%ebp), %eax
877 jmp .Lrcls_epilogue
878
879 .Lrcls_retint:
880 movl -24(%ebp), %eax
881 jmp .Lrcls_epilogue
882
883 .Lrcls_retfloat:
884 flds -24(%ebp)
885 jmp .Lrcls_epilogue
886
887 .Lrcls_retdouble:
888 fldl -24(%ebp)
889 jmp .Lrcls_epilogue
890
891 .Lrcls_retldouble:
892 fldt -24(%ebp)
893 jmp .Lrcls_epilogue
894
895 .Lrcls_retllong:
896 movl -24(%ebp), %eax
897 movl -20(%ebp), %edx
898 jmp .Lrcls_epilogue
899
900 .Lrcls_retstruct1:
901 movsbl -24(%ebp), %eax
902 jmp .Lrcls_epilogue
903
904 .Lrcls_retstruct2:
905 movswl -24(%ebp), %eax
906 jmp .Lrcls_epilogue
907
908 .Lrcls_retstruct4:
909 movl -24(%ebp), %eax
910 jmp .Lrcls_epilogue
911
912 .Lrcls_retstruct:
913 # Nothing to do!
914
915 .Lrcls_noretval:
916 .Lrcls_epilogue:
917 addl $36, %esp
918 popl %esi
919 popl %ebp
920 ret
921 .ffi_closure_raw_SYSV_end:
922 .LFE4:
923
924 #endif /* !FFI_NO_RAW_API */
925
926 # This assumes we are using gas.
927 .balign 16
928 .globl _ffi_closure_STDCALL
929 #ifndef __OS2__
930 .def _ffi_closure_STDCALL; .scl 2; .type 32; .endef
931 #endif
932 _ffi_closure_STDCALL:
933 .LFB5:
934 pushl %ebp
935 .LCFI9:
936 movl %esp, %ebp
937 .LCFI10:
938 subl $40, %esp
939 leal -24(%ebp), %edx
940 movl %edx, -12(%ebp) /* resp */
941 leal 12(%ebp), %edx /* account for stub return address on stack */
942 movl %edx, 4(%esp) /* args */
943 leal -12(%ebp), %edx
944 movl %edx, (%esp) /* &resp */
945 call _ffi_closure_SYSV_inner
946 movl -12(%ebp), %ecx
947 0:
948 call 1f
949 # Do not insert anything here between the call and the jump table.
950 .Lscls_store_table:
951 .long .Lscls_noretval /* FFI_TYPE_VOID */
952 .long .Lscls_retint /* FFI_TYPE_INT */
953 .long .Lscls_retfloat /* FFI_TYPE_FLOAT */
954 .long .Lscls_retdouble /* FFI_TYPE_DOUBLE */
955 .long .Lscls_retldouble /* FFI_TYPE_LONGDOUBLE */
956 .long .Lscls_retuint8 /* FFI_TYPE_UINT8 */
957 .long .Lscls_retsint8 /* FFI_TYPE_SINT8 */
958 .long .Lscls_retuint16 /* FFI_TYPE_UINT16 */
959 .long .Lscls_retsint16 /* FFI_TYPE_SINT16 */
960 .long .Lscls_retint /* FFI_TYPE_UINT32 */
961 .long .Lscls_retint /* FFI_TYPE_SINT32 */
962 .long .Lscls_retllong /* FFI_TYPE_UINT64 */
963 .long .Lscls_retllong /* FFI_TYPE_SINT64 */
964 .long .Lscls_retstruct /* FFI_TYPE_STRUCT */
965 .long .Lscls_retint /* FFI_TYPE_POINTER */
966 .long .Lscls_retstruct1 /* FFI_TYPE_SMALL_STRUCT_1B */
967 .long .Lscls_retstruct2 /* FFI_TYPE_SMALL_STRUCT_2B */
968 .long .Lscls_retstruct4 /* FFI_TYPE_SMALL_STRUCT_4B */
969 1:
970 add %eax, %eax
971 add %eax, %eax
972 add (%esp),%eax
973 add $4, %esp
974 jmp *(%eax)
975
976 /* Sign/zero extend as appropriate. */
977 .Lscls_retsint8:
978 movsbl (%ecx), %eax
979 jmp .Lscls_epilogue
980
981 .Lscls_retsint16:
982 movswl (%ecx), %eax
983 jmp .Lscls_epilogue
984
985 .Lscls_retuint8:
986 movzbl (%ecx), %eax
987 jmp .Lscls_epilogue
988
989 .Lscls_retuint16:
990 movzwl (%ecx), %eax
991 jmp .Lscls_epilogue
992
993 .Lscls_retint:
994 movl (%ecx), %eax
995 jmp .Lscls_epilogue
996
997 .Lscls_retfloat:
998 flds (%ecx)
999 jmp .Lscls_epilogue
1000
1001 .Lscls_retdouble:
1002 fldl (%ecx)
1003 jmp .Lscls_epilogue
1004
1005 .Lscls_retldouble:
1006 fldt (%ecx)
1007 jmp .Lscls_epilogue
1008
1009 .Lscls_retllong:
1010 movl (%ecx), %eax
1011 movl 4(%ecx), %edx
1012 jmp .Lscls_epilogue
1013
1014 .Lscls_retstruct1:
1015 movsbl (%ecx), %eax
1016 jmp .Lscls_epilogue
1017
1018 .Lscls_retstruct2:
1019 movswl (%ecx), %eax
1020 jmp .Lscls_epilogue
1021
1022 .Lscls_retstruct4:
1023 movl (%ecx), %eax
1024 jmp .Lscls_epilogue
1025
1026 .Lscls_retstruct:
1027 # Nothing to do!
1028
1029 .Lscls_noretval:
1030 .Lscls_epilogue:
1031 movl %ebp, %esp
1032 popl %ebp
1033 ret
1034 .ffi_closure_STDCALL_end:
1035 .LFE5:
1036
1037 #ifndef __OS2__
1038 .section .eh_frame,"w"
1039 #endif
1040 .Lframe1:
1041 .LSCIE1:
1042 .long .LECIE1-.LASCIE1 /* Length of Common Information Entry */
1043 .LASCIE1:
1044 .long 0x0 /* CIE Identifier Tag */
1045 .byte 0x1 /* CIE Version */
1046 #ifdef __PIC__
1047 .ascii "zR\0" /* CIE Augmentation */
1048 #else
1049 .ascii "\0" /* CIE Augmentation */
1050 #endif
1051 .byte 0x1 /* .uleb128 0x1; CIE Code Alignment Factor */
1052 .byte 0x7c /* .sleb128 -4; CIE Data Alignment Factor */
1053 .byte 0x8 /* CIE RA Column */
1054 #ifdef __PIC__
1055 .byte 0x1 /* .uleb128 0x1; Augmentation size */
1056 .byte 0x1b /* FDE Encoding (pcrel sdata4) */
1057 #endif
1058 .byte 0xc /* DW_CFA_def_cfa CFA = r4 + 4 = 4(%esp) */
1059 .byte 0x4 /* .uleb128 0x4 */
1060 .byte 0x4 /* .uleb128 0x4 */
1061 .byte 0x88 /* DW_CFA_offset, column 0x8 %eip at CFA + 1 * -4 */
1062 .byte 0x1 /* .uleb128 0x1 */
1063 .align 4
1064 .LECIE1:
1065
1066 .LSFDE1:
1067 .long .LEFDE1-.LASFDE1 /* FDE Length */
1068 .LASFDE1:
1069 .long .LASFDE1-.Lframe1 /* FDE CIE offset */
1070 #if defined __PIC__ && defined HAVE_AS_X86_PCREL
1071 .long .LFB1-. /* FDE initial location */
1072 #else
1073 .long .LFB1
1074 #endif
1075 .long .LFE1-.LFB1 /* FDE address range */
1076 #ifdef __PIC__
1077 .byte 0x0 /* .uleb128 0x0; Augmentation size */
1078 #endif
1079 /* DW_CFA_xxx CFI instructions go here. */
1080
1081 .byte 0x4 /* DW_CFA_advance_loc4 */
1082 .long .LCFI0-.LFB1
1083 .byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
1084 .byte 0x8 /* .uleb128 0x8 */
1085 .byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
1086 .byte 0x2 /* .uleb128 0x2 */
1087
1088 .byte 0x4 /* DW_CFA_advance_loc4 */
1089 .long .LCFI1-.LCFI0
1090 .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
1091 .byte 0x5 /* .uleb128 0x5 */
1092
1093 /* End of DW_CFA_xxx CFI instructions. */
1094 .align 4
1095 .LEFDE1:
1096
1097
1098 .LSFDE3:
1099 .long .LEFDE3-.LASFDE3 /* FDE Length */
1100 .LASFDE3:
1101 .long .LASFDE3-.Lframe1 /* FDE CIE offset */
1102 #if defined __PIC__ && defined HAVE_AS_X86_PCREL
1103 .long .LFB3-. /* FDE initial location */
1104 #else
1105 .long .LFB3
1106 #endif
1107 .long .LFE3-.LFB3 /* FDE address range */
1108 #ifdef __PIC__
1109 .byte 0x0 /* .uleb128 0x0; Augmentation size */
1110 #endif
1111 /* DW_CFA_xxx CFI instructions go here. */
1112
1113 .byte 0x4 /* DW_CFA_advance_loc4 */
1114 .long .LCFI4-.LFB3
1115 .byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
1116 .byte 0x8 /* .uleb128 0x8 */
1117 .byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
1118 .byte 0x2 /* .uleb128 0x2 */
1119
1120 .byte 0x4 /* DW_CFA_advance_loc4 */
1121 .long .LCFI5-.LCFI4
1122 .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
1123 .byte 0x5 /* .uleb128 0x5 */
1124
1125 /* End of DW_CFA_xxx CFI instructions. */
1126 .align 4
1127 .LEFDE3:
1128
1129 #if !FFI_NO_RAW_API
1130
1131 .LSFDE4:
1132 .long .LEFDE4-.LASFDE4 /* FDE Length */
1133 .LASFDE4:
1134 .long .LASFDE4-.Lframe1 /* FDE CIE offset */
1135 #if defined __PIC__ && defined HAVE_AS_X86_PCREL
1136 .long .LFB4-. /* FDE initial location */
1137 #else
1138 .long .LFB4
1139 #endif
1140 .long .LFE4-.LFB4 /* FDE address range */
1141 #ifdef __PIC__
1142 .byte 0x0 /* .uleb128 0x0; Augmentation size */
1143 #endif
1144 /* DW_CFA_xxx CFI instructions go here. */
1145
1146 .byte 0x4 /* DW_CFA_advance_loc4 */
1147 .long .LCFI6-.LFB4
1148 .byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
1149 .byte 0x8 /* .uleb128 0x8 */
1150 .byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
1151 .byte 0x2 /* .uleb128 0x2 */
1152
1153 .byte 0x4 /* DW_CFA_advance_loc4 */
1154 .long .LCFI7-.LCFI6
1155 .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
1156 .byte 0x5 /* .uleb128 0x5 */
1157
1158 .byte 0x4 /* DW_CFA_advance_loc4 */
1159 .long .LCFI8-.LCFI7
1160 .byte 0x86 /* DW_CFA_offset, column 0x6 %esi at CFA + 3 * -4 */
1161 .byte 0x3 /* .uleb128 0x3 */
1162
1163 /* End of DW_CFA_xxx CFI instructions. */
1164 .align 4
1165 .LEFDE4:
1166
1167 #endif /* !FFI_NO_RAW_API */
1168
1169 .LSFDE5:
1170 .long .LEFDE5-.LASFDE5 /* FDE Length */
1171 .LASFDE5:
1172 .long .LASFDE5-.Lframe1 /* FDE CIE offset */
1173 #if defined __PIC__ && defined HAVE_AS_X86_PCREL
1174 .long .LFB5-. /* FDE initial location */
1175 #else
1176 .long .LFB5
1177 #endif
1178 .long .LFE5-.LFB5 /* FDE address range */
1179 #ifdef __PIC__
1180 .byte 0x0 /* .uleb128 0x0; Augmentation size */
1181 #endif
1182 /* DW_CFA_xxx CFI instructions go here. */
1183
1184 .byte 0x4 /* DW_CFA_advance_loc4 */
1185 .long .LCFI9-.LFB5
1186 .byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
1187 .byte 0x8 /* .uleb128 0x8 */
1188 .byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
1189 .byte 0x2 /* .uleb128 0x2 */
1190
1191 .byte 0x4 /* DW_CFA_advance_loc4 */
1192 .long .LCFI10-.LCFI9
1193 .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
1194 .byte 0x5 /* .uleb128 0x5 */
1195
1196 /* End of DW_CFA_xxx CFI instructions. */
1197 .align 4
1198 .LEFDE5:
1199
1200 #endif /* !_MSC_VER */
1201