Static tramp v5 (#624)
[platform/upstream/libffi.git] / src / x86 / sysv.S
1 /* -----------------------------------------------------------------------
2    sysv.S - Copyright (c) 2017  Anthony Green
3           - Copyright (c) 2013  The Written Word, Inc.
4           - Copyright (c) 1996,1998,2001-2003,2005,2008,2010  Red Hat, Inc.
5    
6    X86 Foreign Function Interface 
7
8    Permission is hereby granted, free of charge, to any person obtaining
9    a copy of this software and associated documentation files (the
10    ``Software''), to deal in the Software without restriction, including
11    without limitation the rights to use, copy, modify, merge, publish,
12    distribute, sublicense, and/or sell copies of the Software, and to
13    permit persons to whom the Software is furnished to do so, subject to
14    the following conditions:
15
16    The above copyright notice and this permission notice shall be included
17    in all copies or substantial portions of the Software.
18
19    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
20    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26    DEALINGS IN THE SOFTWARE.
27    ----------------------------------------------------------------------- */
28
29 #ifdef __i386__
30 #ifndef _MSC_VER
31
32 #define LIBFFI_ASM      
33 #include <fficonfig.h>
34 #include <ffi.h>
35 #include "internal.h"
36
37 #define C2(X, Y)  X ## Y
38 #define C1(X, Y)  C2(X, Y)
39 #ifdef __USER_LABEL_PREFIX__
40 # define C(X)     C1(__USER_LABEL_PREFIX__, X)
41 #else
42 # define C(X)     X
43 #endif
44
45 #ifdef X86_DARWIN
46 # define L(X)     C1(L, X)
47 #else
48 # define L(X)     C1(.L, X)
49 #endif
50
51 #ifdef __ELF__
52 # define ENDF(X)  .type X,@function; .size X, . - X
53 #else
54 # define ENDF(X)
55 #endif
56
57 /* Handle win32 fastcall name mangling.  */
58 #ifdef X86_WIN32
59 # define ffi_call_i386          "@ffi_call_i386@8"
60 # define ffi_closure_inner      "@ffi_closure_inner@8"
61 #else
62 # define ffi_call_i386          C(ffi_call_i386)
63 # define ffi_closure_inner      C(ffi_closure_inner)
64 #endif
65
66 /* This macro allows the safe creation of jump tables without an
67    actual table.  The entry points into the table are all 8 bytes.
68    The use of ORG asserts that we're at the correct location.  */
69 /* ??? The clang assembler doesn't handle .org with symbolic expressions.  */
70 #if defined(__clang__) || defined(__APPLE__) || (defined (__sun__) && defined(__svr4__))
71 # define E(BASE, X)     .balign 8
72 #else
73 # define E(BASE, X)     .balign 8; .org BASE + X * 8
74 #endif
75
76         .text
77         .balign 16
78         .globl  ffi_call_i386
79         FFI_HIDDEN(ffi_call_i386)
80
81 /* This is declared as
82
83    void ffi_call_i386(struct call_frame *frame, char *argp)
84         __attribute__((fastcall));
85
86    Thus the arguments are present in
87
88         ecx: frame
89         edx: argp
90 */
91
92 ffi_call_i386:
93 L(UW0):
94         # cfi_startproc
95         _CET_ENDBR
96 #if !HAVE_FASTCALL
97         movl    4(%esp), %ecx
98         movl    8(%esp), %edx
99 #endif
100         movl    (%esp), %eax            /* move the return address */
101         movl    %ebp, (%ecx)            /* store %ebp into local frame */
102         movl    %eax, 4(%ecx)           /* store retaddr into local frame */
103
104         /* New stack frame based off ebp.  This is a itty bit of unwind
105            trickery in that the CFA *has* changed.  There is no easy way
106            to describe it correctly on entry to the function.  Fortunately,
107            it doesn't matter too much since at all points we can correctly
108            unwind back to ffi_call.  Note that the location to which we
109            moved the return address is (the new) CFA-4, so from the
110            perspective of the unwind info, it hasn't moved.  */
111         movl    %ecx, %ebp
112 L(UW1):
113         # cfi_def_cfa(%ebp, 8)
114         # cfi_rel_offset(%ebp, 0)
115
116         movl    %edx, %esp              /* set outgoing argument stack */
117         movl    20+R_EAX*4(%ebp), %eax  /* set register arguments */
118         movl    20+R_EDX*4(%ebp), %edx
119         movl    20+R_ECX*4(%ebp), %ecx
120
121         call    *8(%ebp)
122
123         movl    12(%ebp), %ecx          /* load return type code */
124         movl    %ebx, 8(%ebp)           /* preserve %ebx */
125 L(UW2):
126         # cfi_rel_offset(%ebx, 8)
127
128         andl    $X86_RET_TYPE_MASK, %ecx
129 #ifdef __PIC__
130         call    C(__x86.get_pc_thunk.bx)
131 L(pc1):
132         leal    L(store_table)-L(pc1)(%ebx, %ecx, 8), %ebx
133 #else
134         leal    L(store_table)(,%ecx, 8), %ebx
135 #endif
136         movl    16(%ebp), %ecx          /* load result address */
137         _CET_NOTRACK jmp *%ebx
138
139         .balign 8
140 L(store_table):
141 E(L(store_table), X86_RET_FLOAT)
142         fstps   (%ecx)
143         jmp     L(e1)
144 E(L(store_table), X86_RET_DOUBLE)
145         fstpl   (%ecx)
146         jmp     L(e1)
147 E(L(store_table), X86_RET_LDOUBLE)
148         fstpt   (%ecx)
149         jmp     L(e1)
150 E(L(store_table), X86_RET_SINT8)
151         movsbl  %al, %eax
152         mov     %eax, (%ecx)
153         jmp     L(e1)
154 E(L(store_table), X86_RET_SINT16)
155         movswl  %ax, %eax
156         mov     %eax, (%ecx)
157         jmp     L(e1)
158 E(L(store_table), X86_RET_UINT8)
159         movzbl  %al, %eax
160         mov     %eax, (%ecx)
161         jmp     L(e1)
162 E(L(store_table), X86_RET_UINT16)
163         movzwl  %ax, %eax
164         mov     %eax, (%ecx)
165         jmp     L(e1)
166 E(L(store_table), X86_RET_INT64)
167         movl    %edx, 4(%ecx)
168         /* fallthru */
169 E(L(store_table), X86_RET_INT32)
170         movl    %eax, (%ecx)
171         /* fallthru */
172 E(L(store_table), X86_RET_VOID)
173 L(e1):
174         movl    8(%ebp), %ebx
175         movl    %ebp, %esp
176         popl    %ebp
177 L(UW3):
178         # cfi_remember_state
179         # cfi_def_cfa(%esp, 4)
180         # cfi_restore(%ebx)
181         # cfi_restore(%ebp)
182         ret
183 L(UW4):
184         # cfi_restore_state
185
186 E(L(store_table), X86_RET_STRUCTPOP)
187         jmp     L(e1)
188 E(L(store_table), X86_RET_STRUCTARG)
189         jmp     L(e1)
190 E(L(store_table), X86_RET_STRUCT_1B)
191         movb    %al, (%ecx)
192         jmp     L(e1)
193 E(L(store_table), X86_RET_STRUCT_2B)
194         movw    %ax, (%ecx)
195         jmp     L(e1)
196
197         /* Fill out the table so that bad values are predictable.  */
198 E(L(store_table), X86_RET_UNUSED14)
199         ud2
200 E(L(store_table), X86_RET_UNUSED15)
201         ud2
202
203 L(UW5):
204         # cfi_endproc
205 ENDF(ffi_call_i386)
206
207 /* The inner helper is declared as
208
209    void ffi_closure_inner(struct closure_frame *frame, char *argp)
210         __attribute_((fastcall))
211
212    Thus the arguments are placed in
213
214         ecx:    frame
215         edx:    argp
216 */
217
218 /* Macros to help setting up the closure_data structure.  */
219
220 #if HAVE_FASTCALL
221 # define closure_FS     (40 + 4)
222 # define closure_CF     0
223 #else
224 # define closure_FS     (8 + 40 + 12)
225 # define closure_CF     8
226 #endif
227
228 #define FFI_CLOSURE_SAVE_REGS           \
229         movl    %eax, closure_CF+16+R_EAX*4(%esp);      \
230         movl    %edx, closure_CF+16+R_EDX*4(%esp);      \
231         movl    %ecx, closure_CF+16+R_ECX*4(%esp)
232
233 #define FFI_CLOSURE_COPY_TRAMP_DATA                                     \
234         movl    FFI_TRAMPOLINE_SIZE(%eax), %edx;        /* copy cif */  \
235         movl    FFI_TRAMPOLINE_SIZE+4(%eax), %ecx;      /* copy fun */  \
236         movl    FFI_TRAMPOLINE_SIZE+8(%eax), %eax;      /* copy user_data */ \
237         movl    %edx, closure_CF+28(%esp);                              \
238         movl    %ecx, closure_CF+32(%esp);                              \
239         movl    %eax, closure_CF+36(%esp)
240
241 #if HAVE_FASTCALL
242 # define FFI_CLOSURE_PREP_CALL                                          \
243         movl    %esp, %ecx;                     /* load closure_data */ \
244         leal    closure_FS+4(%esp), %edx;       /* load incoming stack */
245 #else
246 # define FFI_CLOSURE_PREP_CALL                                          \
247         leal    closure_CF(%esp), %ecx;         /* load closure_data */ \
248         leal    closure_FS+4(%esp), %edx;       /* load incoming stack */ \
249         movl    %ecx, (%esp);                                           \
250         movl    %edx, 4(%esp)
251 #endif
252
253 #define FFI_CLOSURE_CALL_INNER(UWN) \
254         call    ffi_closure_inner
255
256 #define FFI_CLOSURE_MASK_AND_JUMP(N, UW)                                \
257         andl    $X86_RET_TYPE_MASK, %eax;                               \
258         leal    L(C1(load_table,N))(, %eax, 8), %edx;                   \
259         movl    closure_CF(%esp), %eax;         /* optimiztic load */   \
260         _CET_NOTRACK jmp *%edx
261
262 #ifdef __PIC__
263 # if defined X86_DARWIN || defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
264 #  undef FFI_CLOSURE_MASK_AND_JUMP
265 #  define FFI_CLOSURE_MASK_AND_JUMP(N, UW)                              \
266         andl    $X86_RET_TYPE_MASK, %eax;                               \
267         call    C(__x86.get_pc_thunk.dx);                               \
268 L(C1(pc,N)):                                                            \
269         leal    L(C1(load_table,N))-L(C1(pc,N))(%edx, %eax, 8), %edx;   \
270         movl    closure_CF(%esp), %eax;         /* optimiztic load */   \
271         _CET_NOTRACK jmp *%edx
272 # else
273 #  define FFI_CLOSURE_CALL_INNER_SAVE_EBX
274 #  undef FFI_CLOSURE_CALL_INNER
275 #  define FFI_CLOSURE_CALL_INNER(UWN)                                   \
276         movl    %ebx, 40(%esp);                 /* save ebx */          \
277 L(C1(UW,UWN)):                                                          \
278         /* cfi_rel_offset(%ebx, 40); */                                 \
279         call    C(__x86.get_pc_thunk.bx);       /* load got register */ \
280         addl    $C(_GLOBAL_OFFSET_TABLE_), %ebx;                        \
281         call    ffi_closure_inner@PLT
282 #  undef FFI_CLOSURE_MASK_AND_JUMP
283 #  define FFI_CLOSURE_MASK_AND_JUMP(N, UWN)                             \
284         andl    $X86_RET_TYPE_MASK, %eax;                               \
285         leal    L(C1(load_table,N))@GOTOFF(%ebx, %eax, 8), %edx;        \
286         movl    40(%esp), %ebx;                 /* restore ebx */       \
287 L(C1(UW,UWN)):                                                          \
288         /* cfi_restore(%ebx); */                                        \
289         movl    closure_CF(%esp), %eax;         /* optimiztic load */   \
290         _CET_NOTRACK jmp *%edx
291 # endif /* DARWIN || HIDDEN */
292 #endif /* __PIC__ */
293
294         .balign 16
295         .globl  C(ffi_go_closure_EAX)
296         FFI_HIDDEN(C(ffi_go_closure_EAX))
297 C(ffi_go_closure_EAX):
298 L(UW6):
299         # cfi_startproc
300         _CET_ENDBR
301         subl    $closure_FS, %esp
302 L(UW7):
303         # cfi_def_cfa_offset(closure_FS + 4)
304         FFI_CLOSURE_SAVE_REGS
305         movl    4(%eax), %edx                   /* copy cif */
306         movl    8(%eax), %ecx                   /* copy fun */
307         movl    %edx, closure_CF+28(%esp)
308         movl    %ecx, closure_CF+32(%esp)
309         movl    %eax, closure_CF+36(%esp)       /* closure is user_data */
310         jmp     L(do_closure_i386)
311 L(UW8):
312         # cfi_endproc
313 ENDF(C(ffi_go_closure_EAX))
314
315         .balign 16
316         .globl  C(ffi_go_closure_ECX)
317         FFI_HIDDEN(C(ffi_go_closure_ECX))
318 C(ffi_go_closure_ECX):
319 L(UW9):
320         # cfi_startproc
321         _CET_ENDBR
322         subl    $closure_FS, %esp
323 L(UW10):
324         # cfi_def_cfa_offset(closure_FS + 4)
325         FFI_CLOSURE_SAVE_REGS
326         movl    4(%ecx), %edx                   /* copy cif */
327         movl    8(%ecx), %eax                   /* copy fun */
328         movl    %edx, closure_CF+28(%esp)
329         movl    %eax, closure_CF+32(%esp)
330         movl    %ecx, closure_CF+36(%esp)       /* closure is user_data */
331         jmp     L(do_closure_i386)
332 L(UW11):
333         # cfi_endproc
334 ENDF(C(ffi_go_closure_ECX))
335
336 /* The closure entry points are reached from the ffi_closure trampoline.
337    On entry, %eax contains the address of the ffi_closure.  */
338
339         .balign 16
340         .globl  C(ffi_closure_i386)
341         FFI_HIDDEN(C(ffi_closure_i386))
342
343 C(ffi_closure_i386):
344 L(UW12):
345         # cfi_startproc
346         _CET_ENDBR
347         subl    $closure_FS, %esp
348 L(UW13):
349         # cfi_def_cfa_offset(closure_FS + 4)
350
351         FFI_CLOSURE_SAVE_REGS
352         FFI_CLOSURE_COPY_TRAMP_DATA
353
354         /* Entry point from preceeding Go closures.  */
355 L(do_closure_i386):
356
357         FFI_CLOSURE_PREP_CALL
358         FFI_CLOSURE_CALL_INNER(14)
359         FFI_CLOSURE_MASK_AND_JUMP(2, 15)
360
361         .balign 8
362 L(load_table2):
363 E(L(load_table2), X86_RET_FLOAT)
364         flds    closure_CF(%esp)
365         jmp     L(e2)
366 E(L(load_table2), X86_RET_DOUBLE)
367         fldl    closure_CF(%esp)
368         jmp     L(e2)
369 E(L(load_table2), X86_RET_LDOUBLE)
370         fldt    closure_CF(%esp)
371         jmp     L(e2)
372 E(L(load_table2), X86_RET_SINT8)
373         movsbl  %al, %eax
374         jmp     L(e2)
375 E(L(load_table2), X86_RET_SINT16)
376         movswl  %ax, %eax
377         jmp     L(e2)
378 E(L(load_table2), X86_RET_UINT8)
379         movzbl  %al, %eax
380         jmp     L(e2)
381 E(L(load_table2), X86_RET_UINT16)
382         movzwl  %ax, %eax
383         jmp     L(e2)
384 E(L(load_table2), X86_RET_INT64)
385         movl    closure_CF+4(%esp), %edx
386         jmp     L(e2)
387 E(L(load_table2), X86_RET_INT32)
388         nop
389         /* fallthru */
390 E(L(load_table2), X86_RET_VOID)
391 L(e2):
392         addl    $closure_FS, %esp
393 L(UW16):
394         # cfi_adjust_cfa_offset(-closure_FS)
395         ret
396 L(UW17):
397         # cfi_adjust_cfa_offset(closure_FS)
398 E(L(load_table2), X86_RET_STRUCTPOP)
399         addl    $closure_FS, %esp
400 L(UW18):
401         # cfi_adjust_cfa_offset(-closure_FS)
402         ret     $4
403 L(UW19):
404         # cfi_adjust_cfa_offset(closure_FS)
405 E(L(load_table2), X86_RET_STRUCTARG)
406         jmp     L(e2)
407 E(L(load_table2), X86_RET_STRUCT_1B)
408         movzbl  %al, %eax
409         jmp     L(e2)
410 E(L(load_table2), X86_RET_STRUCT_2B)
411         movzwl  %ax, %eax
412         jmp     L(e2)
413
414         /* Fill out the table so that bad values are predictable.  */
415 E(L(load_table2), X86_RET_UNUSED14)
416         ud2
417 E(L(load_table2), X86_RET_UNUSED15)
418         ud2
419
420 L(UW20):
421         # cfi_endproc
422 ENDF(C(ffi_closure_i386))
423
424         .balign 16
425         .globl  C(ffi_go_closure_STDCALL)
426         FFI_HIDDEN(C(ffi_go_closure_STDCALL))
427 C(ffi_go_closure_STDCALL):
428 L(UW21):
429         # cfi_startproc
430         _CET_ENDBR
431         subl    $closure_FS, %esp
432 L(UW22):
433         # cfi_def_cfa_offset(closure_FS + 4)
434         FFI_CLOSURE_SAVE_REGS
435         movl    4(%ecx), %edx                   /* copy cif */
436         movl    8(%ecx), %eax                   /* copy fun */
437         movl    %edx, closure_CF+28(%esp)
438         movl    %eax, closure_CF+32(%esp)
439         movl    %ecx, closure_CF+36(%esp)       /* closure is user_data */
440         jmp     L(do_closure_STDCALL)
441 L(UW23):
442         # cfi_endproc
443 ENDF(C(ffi_go_closure_STDCALL))
444
445 /* For REGISTER, we have no available parameter registers, and so we
446    enter here having pushed the closure onto the stack.  */
447
448         .balign 16
449         .globl  C(ffi_closure_REGISTER)
450         FFI_HIDDEN(C(ffi_closure_REGISTER))
451 C(ffi_closure_REGISTER):
452 L(UW24):
453         # cfi_startproc
454         # cfi_def_cfa(%esp, 8)
455         # cfi_offset(%eip, -8)
456         _CET_ENDBR
457         subl    $closure_FS-4, %esp
458 L(UW25):
459         # cfi_def_cfa_offset(closure_FS + 4)
460         FFI_CLOSURE_SAVE_REGS
461         movl    closure_FS-4(%esp), %ecx        /* load retaddr */
462         movl    closure_FS(%esp), %eax          /* load closure */
463         movl    %ecx, closure_FS(%esp)          /* move retaddr */
464         jmp     L(do_closure_REGISTER)
465 L(UW26):
466         # cfi_endproc
467 ENDF(C(ffi_closure_REGISTER))
468
469 /* For STDCALL (and others), we need to pop N bytes of arguments off
470    the stack following the closure.  The amount needing to be popped
471    is returned to us from ffi_closure_inner.  */
472
473         .balign 16
474         .globl  C(ffi_closure_STDCALL)
475         FFI_HIDDEN(C(ffi_closure_STDCALL))
476 C(ffi_closure_STDCALL):
477 L(UW27):
478         # cfi_startproc
479         _CET_ENDBR
480         subl    $closure_FS, %esp
481 L(UW28):
482         # cfi_def_cfa_offset(closure_FS + 4)
483
484         FFI_CLOSURE_SAVE_REGS
485
486         /* Entry point from ffi_closure_REGISTER.  */
487 L(do_closure_REGISTER):
488
489         FFI_CLOSURE_COPY_TRAMP_DATA
490
491         /* Entry point from preceeding Go closure.  */
492 L(do_closure_STDCALL):
493
494         FFI_CLOSURE_PREP_CALL
495         FFI_CLOSURE_CALL_INNER(29)
496
497         movl    %eax, %ecx
498         shrl    $X86_RET_POP_SHIFT, %ecx        /* isolate pop count */
499         leal    closure_FS(%esp, %ecx), %ecx    /* compute popped esp */
500         movl    closure_FS(%esp), %edx          /* move return address */
501         movl    %edx, (%ecx)
502
503         /* From this point on, the value of %esp upon return is %ecx+4,
504            and we've copied the return address to %ecx to make return easy.
505            There's no point in representing this in the unwind info, as
506            there is always a window between the mov and the ret which
507            will be wrong from one point of view or another.  */
508
509         FFI_CLOSURE_MASK_AND_JUMP(3, 30)
510
511         .balign 8
512 L(load_table3):
513 E(L(load_table3), X86_RET_FLOAT)
514         flds    closure_CF(%esp)
515         movl    %ecx, %esp
516         ret
517 E(L(load_table3), X86_RET_DOUBLE)
518         fldl    closure_CF(%esp)
519         movl    %ecx, %esp
520         ret
521 E(L(load_table3), X86_RET_LDOUBLE)
522         fldt    closure_CF(%esp)
523         movl    %ecx, %esp
524         ret
525 E(L(load_table3), X86_RET_SINT8)
526         movsbl  %al, %eax
527         movl    %ecx, %esp
528         ret
529 E(L(load_table3), X86_RET_SINT16)
530         movswl  %ax, %eax
531         movl    %ecx, %esp
532         ret
533 E(L(load_table3), X86_RET_UINT8)
534         movzbl  %al, %eax
535         movl    %ecx, %esp
536         ret
537 E(L(load_table3), X86_RET_UINT16)
538         movzwl  %ax, %eax
539         movl    %ecx, %esp
540         ret
541 E(L(load_table3), X86_RET_INT64)
542         movl    closure_CF+4(%esp), %edx
543         movl    %ecx, %esp
544         ret
545 E(L(load_table3), X86_RET_INT32)
546         movl    %ecx, %esp
547         ret
548 E(L(load_table3), X86_RET_VOID)
549         movl    %ecx, %esp
550         ret
551 E(L(load_table3), X86_RET_STRUCTPOP)
552         movl    %ecx, %esp
553         ret
554 E(L(load_table3), X86_RET_STRUCTARG)
555         movl    %ecx, %esp
556         ret
557 E(L(load_table3), X86_RET_STRUCT_1B)
558         movzbl  %al, %eax
559         movl    %ecx, %esp
560         ret
561 E(L(load_table3), X86_RET_STRUCT_2B)
562         movzwl  %ax, %eax
563         movl    %ecx, %esp
564         ret
565
566         /* Fill out the table so that bad values are predictable.  */
567 E(L(load_table3), X86_RET_UNUSED14)
568         ud2
569 E(L(load_table3), X86_RET_UNUSED15)
570         ud2
571
572 L(UW31):
573         # cfi_endproc
574 ENDF(C(ffi_closure_STDCALL))
575
576 #if defined(FFI_EXEC_STATIC_TRAMP)
577         .balign 16
578         .globl  C(ffi_closure_i386_alt)
579         FFI_HIDDEN(C(ffi_closure_i386_alt))
580 C(ffi_closure_i386_alt):
581         /* See the comments above trampoline_code_table. */
582         _CET_ENDBR
583         movl    4(%esp), %eax                   /* Load closure in eax */
584         add     $8, %esp                        /* Restore the stack */
585         jmp     C(ffi_closure_i386)
586 ENDF(C(ffi_closure_i386_alt))
587
588         .balign 16
589         .globl  C(ffi_closure_REGISTER_alt)
590         FFI_HIDDEN(C(ffi_closure_REGISTER_alt))
591 C(ffi_closure_REGISTER_alt):
592         /* See the comments above trampoline_code_table. */
593         _CET_ENDBR
594         movl    (%esp), %eax                    /* Restore eax */
595         add     $4, %esp                        /* Leave closure on stack */
596         jmp     C(ffi_closure_REGISTER)
597 ENDF(C(ffi_closure_REGISTER_alt))
598
599         .balign 16
600         .globl  C(ffi_closure_STDCALL_alt)
601         FFI_HIDDEN(C(ffi_closure_STDCALL_alt))
602 C(ffi_closure_STDCALL_alt):
603         /* See the comments above trampoline_code_table. */
604         _CET_ENDBR
605         movl    4(%esp), %eax                   /* Load closure in eax */
606         add     $8, %esp                        /* Restore the stack */
607         jmp     C(ffi_closure_STDCALL)
608 ENDF(C(ffi_closure_STDCALL_alt))
609
610 /*
611  * Below is the definition of the trampoline code table. Each element in
612  * the code table is a trampoline.
613  *
614  * Because we jump to the trampoline, we place a _CET_ENDBR at the
615  * beginning of the trampoline to mark it as a valid branch target. This is
616  * part of the the Intel CET (Control Flow Enforcement Technology).
617  */
618 /*
619  * The trampoline uses register eax.  It saves the original value of eax on
620  * the stack.
621  *
622  * The trampoline has two parameters - target code to jump to and data for
623  * the target code. The trampoline extracts the parameters from its parameter
624  * block (see tramp_table_map()). The trampoline saves the data address on
625  * the stack. Finally, it jumps to the target code.
626  *
627  * The target code can choose to:
628  *
629  * - restore the value of eax
630  * - load the data address in a register
631  * - restore the stack pointer to what it was when the trampoline was invoked.
632  */
633 #ifdef ENDBR_PRESENT
634 #define X86_DATA_OFFSET         4081
635 #define X86_CODE_OFFSET         4070
636 #else
637 #define X86_DATA_OFFSET         4085
638 #define X86_CODE_OFFSET         4074
639 #endif
640
641         .align  X86_TRAMP_MAP_SIZE
642         .globl  C(trampoline_code_table)
643         FFI_HIDDEN(C(trampoline_code_table))
644 C(trampoline_code_table):
645         .rept   X86_TRAMP_MAP_SIZE / X86_TRAMP_SIZE
646         _CET_ENDBR
647         sub     $8, %esp
648         movl    %eax, (%esp)                    /* Save %eax on stack */
649         call    1f                              /* Get next PC into %eax */
650         movl    X86_DATA_OFFSET(%eax), %eax     /* Copy data into %eax */
651         movl    %eax, 4(%esp)                   /* Save data on stack */
652         call    1f                              /* Get next PC into %eax */
653         movl    X86_CODE_OFFSET(%eax), %eax     /* Copy code into %eax */
654         jmp     *%eax                           /* Jump to code */
655 1:
656         mov     (%esp), %eax
657         ret
658         .align  4
659         .endr
660 ENDF(C(trampoline_code_table))
661         .align  X86_TRAMP_MAP_SIZE
662 #endif /* FFI_EXEC_STATIC_TRAMP */
663
664 #if !FFI_NO_RAW_API
665
666 #define raw_closure_S_FS        (16+16+12)
667
668         .balign 16
669         .globl  C(ffi_closure_raw_SYSV)
670         FFI_HIDDEN(C(ffi_closure_raw_SYSV))
671 C(ffi_closure_raw_SYSV):
672 L(UW32):
673         # cfi_startproc
674         _CET_ENDBR
675         subl    $raw_closure_S_FS, %esp
676 L(UW33):
677         # cfi_def_cfa_offset(raw_closure_S_FS + 4)
678         movl    %ebx, raw_closure_S_FS-4(%esp)
679 L(UW34):
680         # cfi_rel_offset(%ebx, raw_closure_S_FS-4)
681
682         movl    FFI_TRAMPOLINE_SIZE+8(%eax), %edx       /* load cl->user_data */
683         movl    %edx, 12(%esp)
684         leal    raw_closure_S_FS+4(%esp), %edx          /* load raw_args */
685         movl    %edx, 8(%esp)
686         leal    16(%esp), %edx                          /* load &res */
687         movl    %edx, 4(%esp)
688         movl    FFI_TRAMPOLINE_SIZE(%eax), %ebx         /* load cl->cif */
689         movl    %ebx, (%esp)
690         call    *FFI_TRAMPOLINE_SIZE+4(%eax)            /* call cl->fun */
691
692         movl    20(%ebx), %eax                          /* load cif->flags */
693         andl    $X86_RET_TYPE_MASK, %eax
694 #ifdef __PIC__
695         call    C(__x86.get_pc_thunk.bx)
696 L(pc4):
697         leal    L(load_table4)-L(pc4)(%ebx, %eax, 8), %ecx
698 #else
699         leal    L(load_table4)(,%eax, 8), %ecx
700 #endif
701         movl    raw_closure_S_FS-4(%esp), %ebx
702 L(UW35):
703         # cfi_restore(%ebx)
704         movl    16(%esp), %eax                          /* Optimistic load */
705         jmp     *%ecx
706
707         .balign 8
708 L(load_table4):
709 E(L(load_table4), X86_RET_FLOAT)
710         flds    16(%esp)
711         jmp     L(e4)
712 E(L(load_table4), X86_RET_DOUBLE)
713         fldl    16(%esp)
714         jmp     L(e4)
715 E(L(load_table4), X86_RET_LDOUBLE)
716         fldt    16(%esp)
717         jmp     L(e4)
718 E(L(load_table4), X86_RET_SINT8)
719         movsbl  %al, %eax
720         jmp     L(e4)
721 E(L(load_table4), X86_RET_SINT16)
722         movswl  %ax, %eax
723         jmp     L(e4)
724 E(L(load_table4), X86_RET_UINT8)
725         movzbl  %al, %eax
726         jmp     L(e4)
727 E(L(load_table4), X86_RET_UINT16)
728         movzwl  %ax, %eax
729         jmp     L(e4)
730 E(L(load_table4), X86_RET_INT64)
731         movl    16+4(%esp), %edx
732         jmp     L(e4)
733 E(L(load_table4), X86_RET_INT32)
734         nop
735         /* fallthru */
736 E(L(load_table4), X86_RET_VOID)
737 L(e4):
738         addl    $raw_closure_S_FS, %esp
739 L(UW36):
740         # cfi_adjust_cfa_offset(-raw_closure_S_FS)
741         ret
742 L(UW37):
743         # cfi_adjust_cfa_offset(raw_closure_S_FS)
744 E(L(load_table4), X86_RET_STRUCTPOP)
745         addl    $raw_closure_S_FS, %esp
746 L(UW38):
747         # cfi_adjust_cfa_offset(-raw_closure_S_FS)
748         ret     $4
749 L(UW39):
750         # cfi_adjust_cfa_offset(raw_closure_S_FS)
751 E(L(load_table4), X86_RET_STRUCTARG)
752         jmp     L(e4)
753 E(L(load_table4), X86_RET_STRUCT_1B)
754         movzbl  %al, %eax
755         jmp     L(e4)
756 E(L(load_table4), X86_RET_STRUCT_2B)
757         movzwl  %ax, %eax
758         jmp     L(e4)
759
760         /* Fill out the table so that bad values are predictable.  */
761 E(L(load_table4), X86_RET_UNUSED14)
762         ud2
763 E(L(load_table4), X86_RET_UNUSED15)
764         ud2
765
766 L(UW40):
767         # cfi_endproc
768 ENDF(C(ffi_closure_raw_SYSV))
769
770 #define raw_closure_T_FS        (16+16+8)
771
772         .balign 16
773         .globl  C(ffi_closure_raw_THISCALL)
774         FFI_HIDDEN(C(ffi_closure_raw_THISCALL))
775 C(ffi_closure_raw_THISCALL):
776 L(UW41):
777         # cfi_startproc
778         _CET_ENDBR
779         /* Rearrange the stack such that %ecx is the first argument.
780            This means moving the return address.  */
781         popl    %edx
782 L(UW42):
783         # cfi_def_cfa_offset(0)
784         # cfi_register(%eip, %edx)
785         pushl   %ecx
786 L(UW43):
787         # cfi_adjust_cfa_offset(4)
788         pushl   %edx
789 L(UW44):
790         # cfi_adjust_cfa_offset(4)
791         # cfi_rel_offset(%eip, 0)
792         subl    $raw_closure_T_FS, %esp
793 L(UW45):
794         # cfi_adjust_cfa_offset(raw_closure_T_FS)
795         movl    %ebx, raw_closure_T_FS-4(%esp)
796 L(UW46):
797         # cfi_rel_offset(%ebx, raw_closure_T_FS-4)
798
799         movl    FFI_TRAMPOLINE_SIZE+8(%eax), %edx       /* load cl->user_data */
800         movl    %edx, 12(%esp)
801         leal    raw_closure_T_FS+4(%esp), %edx          /* load raw_args */
802         movl    %edx, 8(%esp)
803         leal    16(%esp), %edx                          /* load &res */
804         movl    %edx, 4(%esp)
805         movl    FFI_TRAMPOLINE_SIZE(%eax), %ebx         /* load cl->cif */
806         movl    %ebx, (%esp)
807         call    *FFI_TRAMPOLINE_SIZE+4(%eax)            /* call cl->fun */
808
809         movl    20(%ebx), %eax                          /* load cif->flags */
810         andl    $X86_RET_TYPE_MASK, %eax
811 #ifdef __PIC__
812         call    C(__x86.get_pc_thunk.bx)
813 L(pc5):
814         leal    L(load_table5)-L(pc5)(%ebx, %eax, 8), %ecx
815 #else
816         leal    L(load_table5)(,%eax, 8), %ecx
817 #endif
818         movl    raw_closure_T_FS-4(%esp), %ebx
819 L(UW47):
820         # cfi_restore(%ebx)
821         movl    16(%esp), %eax                          /* Optimistic load */
822         jmp     *%ecx
823
824         .balign 8
825 L(load_table5):
826 E(L(load_table5), X86_RET_FLOAT)
827         flds    16(%esp)
828         jmp     L(e5)
829 E(L(load_table5), X86_RET_DOUBLE)
830         fldl    16(%esp)
831         jmp     L(e5)
832 E(L(load_table5), X86_RET_LDOUBLE)
833         fldt    16(%esp)
834         jmp     L(e5)
835 E(L(load_table5), X86_RET_SINT8)
836         movsbl  %al, %eax
837         jmp     L(e5)
838 E(L(load_table5), X86_RET_SINT16)
839         movswl  %ax, %eax
840         jmp     L(e5)
841 E(L(load_table5), X86_RET_UINT8)
842         movzbl  %al, %eax
843         jmp     L(e5)
844 E(L(load_table5), X86_RET_UINT16)
845         movzwl  %ax, %eax
846         jmp     L(e5)
847 E(L(load_table5), X86_RET_INT64)
848         movl    16+4(%esp), %edx
849         jmp     L(e5)
850 E(L(load_table5), X86_RET_INT32)
851         nop
852         /* fallthru */
853 E(L(load_table5), X86_RET_VOID)
854 L(e5):
855         addl    $raw_closure_T_FS, %esp
856 L(UW48):
857         # cfi_adjust_cfa_offset(-raw_closure_T_FS)
858         /* Remove the extra %ecx argument we pushed.  */
859         ret     $4
860 L(UW49):
861         # cfi_adjust_cfa_offset(raw_closure_T_FS)
862 E(L(load_table5), X86_RET_STRUCTPOP)
863         addl    $raw_closure_T_FS, %esp
864 L(UW50):
865         # cfi_adjust_cfa_offset(-raw_closure_T_FS)
866         ret     $8
867 L(UW51):
868         # cfi_adjust_cfa_offset(raw_closure_T_FS)
869 E(L(load_table5), X86_RET_STRUCTARG)
870         jmp     L(e5)
871 E(L(load_table5), X86_RET_STRUCT_1B)
872         movzbl  %al, %eax
873         jmp     L(e5)
874 E(L(load_table5), X86_RET_STRUCT_2B)
875         movzwl  %ax, %eax
876         jmp     L(e5)
877
878         /* Fill out the table so that bad values are predictable.  */
879 E(L(load_table5), X86_RET_UNUSED14)
880         ud2
881 E(L(load_table5), X86_RET_UNUSED15)
882         ud2
883
884 L(UW52):
885         # cfi_endproc
886 ENDF(C(ffi_closure_raw_THISCALL))
887
888 #endif /* !FFI_NO_RAW_API */
889
890 #ifdef X86_DARWIN
891 # define COMDAT(X)                                                      \
892         .section __TEXT,__text,coalesced,pure_instructions;             \
893         .weak_definition X;                                             \
894         FFI_HIDDEN(X)
895 #elif defined __ELF__ && !(defined(__sun__) && defined(__svr4__))
896 # define COMDAT(X)                                                      \
897         .section .text.X,"axG",@progbits,X,comdat;                      \
898         .globl  X;                                                      \
899         FFI_HIDDEN(X)
900 #else
901 # define COMDAT(X)
902 #endif
903
904 #if defined(__PIC__)
905         COMDAT(C(__x86.get_pc_thunk.bx))
906 C(__x86.get_pc_thunk.bx):
907         movl    (%esp), %ebx
908         ret
909 ENDF(C(__x86.get_pc_thunk.bx))
910 # if defined X86_DARWIN || defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
911         COMDAT(C(__x86.get_pc_thunk.dx))
912 C(__x86.get_pc_thunk.dx):
913         movl    (%esp), %edx
914         ret
915 ENDF(C(__x86.get_pc_thunk.dx))
916 #endif /* DARWIN || HIDDEN */
917 #endif /* __PIC__ */
918
919 /* Sadly, OSX cctools-as doesn't understand .cfi directives at all.  */
920
921 #ifdef __APPLE__
922 .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
923 EHFrame0:
924 #elif defined(X86_WIN32)
925 .section .eh_frame,"r"
926 #elif defined(HAVE_AS_X86_64_UNWIND_SECTION_TYPE)
927 .section .eh_frame,EH_FRAME_FLAGS,@unwind
928 #else
929 .section .eh_frame,EH_FRAME_FLAGS,@progbits
930 #endif
931
932 #ifdef HAVE_AS_X86_PCREL
933 # define PCREL(X)       X - .
934 #else
935 # define PCREL(X)       X@rel
936 #endif
937
938 /* Simplify advancing between labels.  Assume DW_CFA_advance_loc1 fits.  */
939 #define ADV(N, P)       .byte 2, L(N)-L(P)
940
941         .balign 4
942 L(CIE):
943         .set    L(set0),L(ECIE)-L(SCIE)
944         .long   L(set0)                 /* CIE Length */
945 L(SCIE):
946         .long   0                       /* CIE Identifier Tag */
947         .byte   1                       /* CIE Version */
948         .ascii  "zR\0"                  /* CIE Augmentation */
949         .byte   1                       /* CIE Code Alignment Factor */
950         .byte   0x7c                    /* CIE Data Alignment Factor */
951         .byte   0x8                     /* CIE RA Column */
952         .byte   1                       /* Augmentation size */
953         .byte   0x1b                    /* FDE Encoding (pcrel sdata4) */
954         .byte   0xc, 4, 4               /* DW_CFA_def_cfa, %esp offset 4 */
955         .byte   0x80+8, 1               /* DW_CFA_offset, %eip offset 1*-4 */
956         .balign 4
957 L(ECIE):
958
959         .set    L(set1),L(EFDE1)-L(SFDE1)
960         .long   L(set1)                 /* FDE Length */
961 L(SFDE1):
962         .long   L(SFDE1)-L(CIE)         /* FDE CIE offset */
963         .long   PCREL(L(UW0))           /* Initial location */
964         .long   L(UW5)-L(UW0)           /* Address range */
965         .byte   0                       /* Augmentation size */
966         ADV(UW1, UW0)
967         .byte   0xc, 5, 8               /* DW_CFA_def_cfa, %ebp 8 */
968         .byte   0x80+5, 2               /* DW_CFA_offset, %ebp 2*-4 */
969         ADV(UW2, UW1)
970         .byte   0x80+3, 0               /* DW_CFA_offset, %ebx 0*-4 */
971         ADV(UW3, UW2)
972         .byte   0xa                     /* DW_CFA_remember_state */
973         .byte   0xc, 4, 4               /* DW_CFA_def_cfa, %esp 4 */
974         .byte   0xc0+3                  /* DW_CFA_restore, %ebx */
975         .byte   0xc0+5                  /* DW_CFA_restore, %ebp */
976         ADV(UW4, UW3)
977         .byte   0xb                     /* DW_CFA_restore_state */
978         .balign 4
979 L(EFDE1):
980
981         .set    L(set2),L(EFDE2)-L(SFDE2)
982         .long   L(set2)                 /* FDE Length */
983 L(SFDE2):
984         .long   L(SFDE2)-L(CIE)         /* FDE CIE offset */
985         .long   PCREL(L(UW6))           /* Initial location */
986         .long   L(UW8)-L(UW6)           /* Address range */
987         .byte   0                       /* Augmentation size */
988         ADV(UW7, UW6)
989         .byte   0xe, closure_FS+4       /* DW_CFA_def_cfa_offset */
990         .balign 4
991 L(EFDE2):
992
993         .set    L(set3),L(EFDE3)-L(SFDE3)
994         .long   L(set3)                 /* FDE Length */
995 L(SFDE3):
996         .long   L(SFDE3)-L(CIE)         /* FDE CIE offset */
997         .long   PCREL(L(UW9))           /* Initial location */
998         .long   L(UW11)-L(UW9)          /* Address range */
999         .byte   0                       /* Augmentation size */
1000         ADV(UW10, UW9)
1001         .byte   0xe, closure_FS+4       /* DW_CFA_def_cfa_offset */
1002         .balign 4
1003 L(EFDE3):
1004
1005         .set    L(set4),L(EFDE4)-L(SFDE4)
1006         .long   L(set4)                 /* FDE Length */
1007 L(SFDE4):
1008         .long   L(SFDE4)-L(CIE)         /* FDE CIE offset */
1009         .long   PCREL(L(UW12))          /* Initial location */
1010         .long   L(UW20)-L(UW12)         /* Address range */
1011         .byte   0                       /* Augmentation size */
1012         ADV(UW13, UW12)
1013         .byte   0xe, closure_FS+4       /* DW_CFA_def_cfa_offset */
1014 #ifdef FFI_CLOSURE_CALL_INNER_SAVE_EBX
1015         ADV(UW14, UW13)
1016         .byte   0x80+3, (40-(closure_FS+4))/-4  /* DW_CFA_offset %ebx */
1017         ADV(UW15, UW14)
1018         .byte   0xc0+3                  /* DW_CFA_restore %ebx */
1019         ADV(UW16, UW15)
1020 #else
1021         ADV(UW16, UW13)
1022 #endif
1023         .byte   0xe, 4                  /* DW_CFA_def_cfa_offset */
1024         ADV(UW17, UW16)
1025         .byte   0xe, closure_FS+4       /* DW_CFA_def_cfa_offset */
1026         ADV(UW18, UW17)
1027         .byte   0xe, 4                  /* DW_CFA_def_cfa_offset */
1028         ADV(UW19, UW18)
1029         .byte   0xe, closure_FS+4       /* DW_CFA_def_cfa_offset */
1030         .balign 4
1031 L(EFDE4):
1032
1033         .set    L(set5),L(EFDE5)-L(SFDE5)
1034         .long   L(set5)                 /* FDE Length */
1035 L(SFDE5):
1036         .long   L(SFDE5)-L(CIE)         /* FDE CIE offset */
1037         .long   PCREL(L(UW21))          /* Initial location */
1038         .long   L(UW23)-L(UW21)         /* Address range */
1039         .byte   0                       /* Augmentation size */
1040         ADV(UW22, UW21)
1041         .byte   0xe, closure_FS+4       /* DW_CFA_def_cfa_offset */
1042         .balign 4
1043 L(EFDE5):
1044
1045         .set    L(set6),L(EFDE6)-L(SFDE6)
1046         .long   L(set6)                 /* FDE Length */
1047 L(SFDE6):
1048         .long   L(SFDE6)-L(CIE)         /* FDE CIE offset */
1049         .long   PCREL(L(UW24))          /* Initial location */
1050         .long   L(UW26)-L(UW24)         /* Address range */
1051         .byte   0                       /* Augmentation size */
1052         .byte   0xe, 8                  /* DW_CFA_def_cfa_offset */
1053         .byte   0x80+8, 2               /* DW_CFA_offset %eip, 2*-4 */
1054         ADV(UW25, UW24)
1055         .byte   0xe, closure_FS+4       /* DW_CFA_def_cfa_offset */
1056         .balign 4
1057 L(EFDE6):
1058
1059         .set    L(set7),L(EFDE7)-L(SFDE7)
1060         .long   L(set7)                 /* FDE Length */
1061 L(SFDE7):
1062         .long   L(SFDE7)-L(CIE)         /* FDE CIE offset */
1063         .long   PCREL(L(UW27))          /* Initial location */
1064         .long   L(UW31)-L(UW27)         /* Address range */
1065         .byte   0                       /* Augmentation size */
1066         ADV(UW28, UW27)
1067         .byte   0xe, closure_FS+4       /* DW_CFA_def_cfa_offset */
1068 #ifdef FFI_CLOSURE_CALL_INNER_SAVE_EBX
1069         ADV(UW29, UW28)
1070         .byte   0x80+3, (40-(closure_FS+4))/-4  /* DW_CFA_offset %ebx */
1071         ADV(UW30, UW29)
1072         .byte   0xc0+3                  /* DW_CFA_restore %ebx */
1073 #endif
1074         .balign 4
1075 L(EFDE7):
1076
1077 #if !FFI_NO_RAW_API
1078         .set    L(set8),L(EFDE8)-L(SFDE8)
1079         .long   L(set8)                 /* FDE Length */
1080 L(SFDE8):
1081         .long   L(SFDE8)-L(CIE)         /* FDE CIE offset */
1082         .long   PCREL(L(UW32))          /* Initial location */
1083         .long   L(UW40)-L(UW32)         /* Address range */
1084         .byte   0                       /* Augmentation size */
1085         ADV(UW33, UW32)
1086         .byte   0xe, raw_closure_S_FS+4 /* DW_CFA_def_cfa_offset */
1087         ADV(UW34, UW33)
1088         .byte   0x80+3, 2               /* DW_CFA_offset %ebx 2*-4 */
1089         ADV(UW35, UW34)
1090         .byte   0xc0+3                  /* DW_CFA_restore %ebx */
1091         ADV(UW36, UW35)
1092         .byte   0xe, 4                  /* DW_CFA_def_cfa_offset */
1093         ADV(UW37, UW36)
1094         .byte   0xe, raw_closure_S_FS+4 /* DW_CFA_def_cfa_offset */
1095         ADV(UW38, UW37)
1096         .byte   0xe, 4                  /* DW_CFA_def_cfa_offset */
1097         ADV(UW39, UW38)
1098         .byte   0xe, raw_closure_S_FS+4 /* DW_CFA_def_cfa_offset */
1099         .balign 4
1100 L(EFDE8):
1101
1102         .set    L(set9),L(EFDE9)-L(SFDE9)
1103         .long   L(set9)                 /* FDE Length */
1104 L(SFDE9):
1105         .long   L(SFDE9)-L(CIE)         /* FDE CIE offset */
1106         .long   PCREL(L(UW41))          /* Initial location */
1107         .long   L(UW52)-L(UW41)         /* Address range */
1108         .byte   0                       /* Augmentation size */
1109         ADV(UW42, UW41)
1110         .byte   0xe, 0                  /* DW_CFA_def_cfa_offset */
1111         .byte   0x9, 8, 2               /* DW_CFA_register %eip, %edx */
1112         ADV(UW43, UW42)
1113         .byte   0xe, 4                  /* DW_CFA_def_cfa_offset */
1114         ADV(UW44, UW43)
1115         .byte   0xe, 8                  /* DW_CFA_def_cfa_offset */
1116         .byte   0x80+8, 2               /* DW_CFA_offset %eip 2*-4 */
1117         ADV(UW45, UW44)
1118         .byte   0xe, raw_closure_T_FS+8 /* DW_CFA_def_cfa_offset */
1119         ADV(UW46, UW45)
1120         .byte   0x80+3, 3               /* DW_CFA_offset %ebx 3*-4 */
1121         ADV(UW47, UW46)
1122         .byte   0xc0+3                  /* DW_CFA_restore %ebx */
1123         ADV(UW48, UW47)
1124         .byte   0xe, 8                  /* DW_CFA_def_cfa_offset */
1125         ADV(UW49, UW48)
1126         .byte   0xe, raw_closure_T_FS+8 /* DW_CFA_def_cfa_offset */
1127         ADV(UW50, UW49)
1128         .byte   0xe, 8                  /* DW_CFA_def_cfa_offset */
1129         ADV(UW51, UW50)
1130         .byte   0xe, raw_closure_T_FS+8 /* DW_CFA_def_cfa_offset */
1131         .balign 4
1132 L(EFDE9):
1133 #endif /* !FFI_NO_RAW_API */
1134
1135 #ifdef _WIN32
1136         .def     @feat.00;
1137         .scl    3;
1138         .type   0;
1139         .endef
1140         .globl  @feat.00
1141 @feat.00 = 1
1142 #endif
1143
1144 #ifdef __APPLE__
1145     .subsections_via_symbols
1146     .section __LD,__compact_unwind,regular,debug
1147
1148     /* compact unwind for ffi_call_i386 */
1149     .long    C(ffi_call_i386)
1150     .set     L1,L(UW5)-L(UW0)
1151     .long    L1
1152     .long    0x04000000 /* use dwarf unwind info */
1153     .long    0
1154     .long    0
1155
1156     /* compact unwind for ffi_go_closure_EAX */
1157     .long    C(ffi_go_closure_EAX)
1158     .set     L2,L(UW8)-L(UW6)
1159     .long    L2
1160     .long    0x04000000 /* use dwarf unwind info */
1161     .long    0
1162     .long    0
1163
1164     /* compact unwind for ffi_go_closure_ECX */
1165     .long    C(ffi_go_closure_ECX)
1166     .set     L3,L(UW11)-L(UW9)
1167     .long    L3
1168     .long    0x04000000 /* use dwarf unwind info */
1169     .long    0
1170     .long    0
1171
1172     /* compact unwind for ffi_closure_i386 */
1173     .long    C(ffi_closure_i386)
1174     .set     L4,L(UW20)-L(UW12)
1175     .long    L4
1176     .long    0x04000000 /* use dwarf unwind info */
1177     .long    0
1178     .long    0
1179
1180     /* compact unwind for ffi_go_closure_STDCALL */
1181     .long    C(ffi_go_closure_STDCALL)
1182     .set     L5,L(UW23)-L(UW21)
1183     .long    L5
1184     .long    0x04000000 /* use dwarf unwind info */
1185     .long    0
1186     .long    0
1187
1188     /* compact unwind for ffi_closure_REGISTER */
1189     .long    C(ffi_closure_REGISTER)
1190     .set     L6,L(UW26)-L(UW24)
1191     .long    L6
1192     .long    0x04000000 /* use dwarf unwind info */
1193     .long    0
1194     .long    0
1195
1196     /* compact unwind for ffi_closure_STDCALL */
1197     .long    C(ffi_closure_STDCALL)
1198     .set     L7,L(UW31)-L(UW27)
1199     .long    L7
1200     .long    0x04000000 /* use dwarf unwind info */
1201     .long    0
1202     .long    0
1203
1204     /* compact unwind for ffi_closure_raw_SYSV */
1205     .long    C(ffi_closure_raw_SYSV)
1206     .set     L8,L(UW40)-L(UW32)
1207     .long    L8
1208     .long    0x04000000 /* use dwarf unwind info */
1209     .long    0
1210     .long    0
1211
1212     /* compact unwind for ffi_closure_raw_THISCALL */
1213     .long    C(ffi_closure_raw_THISCALL)
1214     .set     L9,L(UW52)-L(UW41)
1215     .long    L9
1216     .long    0x04000000 /* use dwarf unwind info */
1217     .long    0
1218     .long    0
1219 #endif /* __APPLE__ */
1220
1221 #endif /* ifndef _MSC_VER */
1222
1223 #endif /* ifdef __i386__ */
1224
1225 #if defined __ELF__ && defined __linux__
1226         .section        .note.GNU-stack,"",@progbits
1227 #endif