x86: Use win32 name mangling for fastcall functions
[libffi.git] / src / x86 / sysv.S
1 /* -----------------------------------------------------------------------
2    sysv.S - Copyright (c) 2013  The Written Word, Inc.
3           - Copyright (c) 1996,1998,2001-2003,2005,2008,2010  Red Hat, Inc.
4    
5    X86 Foreign Function Interface 
6
7    Permission is hereby granted, free of charge, to any person obtaining
8    a copy of this software and associated documentation files (the
9    ``Software''), to deal in the Software without restriction, including
10    without limitation the rights to use, copy, modify, merge, publish,
11    distribute, sublicense, and/or sell copies of the Software, and to
12    permit persons to whom the Software is furnished to do so, subject to
13    the following conditions:
14
15    The above copyright notice and this permission notice shall be included
16    in all copies or substantial portions of the Software.
17
18    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25    DEALINGS IN THE SOFTWARE.
26    ----------------------------------------------------------------------- */
27
28 #ifndef __x86_64__
29
30 #define LIBFFI_ASM      
31 #include <fficonfig.h>
32 #include <ffi.h>
33 #include <ffi_cfi.h>
34 #include "internal.h"
35
36 #define C2(X, Y)  X ## Y
37 #define C1(X, Y)  C2(X, Y)
38 #ifdef __USER_LABEL_PREFIX__
39 # define C(X)     C1(__USER_LABEL_PREFIX__, X)
40 #else
41 # define C(X)     X
42 #endif
43
44 #ifdef __ELF__
45 # define ENDF(X)  .type X,@function; .size X, . - X
46 #else
47 # define ENDF(X)
48 #endif
49
50 /* Handle win32 fastcall name mangling.  */
51 #ifdef X86_WIN32
52 # define ffi_call_i386          @ffi_call_i386@8
53 # define ffi_closure_inner      @ffi_closure_inner@8
54 #else
55 # define ffi_call_i386          C(ffi_call_i386)
56 # define ffi_closure_inner      C(ffi_closure_inner)
57 #endif
58
59 /* This macro allows the safe creation of jump tables without an
60    actual table.  The entry points into the table are all 8 bytes.
61    The use of ORG asserts that we're at the correct location.  */
62 #define E(X)      .align 8; .org 0b + X * 8
63
64         .text
65         .align  16
66         .globl  ffi_call_i386
67         FFI_HIDDEN(ffi_call_i386)
68
69 /* This is declared as
70
71    void ffi_call_i386(struct call_frame *frame, char *argp)
72         __attribute__((fastcall));
73
74    Thus the arguments are present in
75
76         ecx: frame
77         edx: argp
78 */
79
80 ffi_call_i386:
81         cfi_startproc
82         movl    (%esp), %eax            /* move the return address */
83         movl    %ebp, (%ecx)            /* store %ebp into local frame */
84         movl    %eax, 4(%ecx)           /* store retaddr into local frame */
85
86         /* New stack frame based off ebp.  This is a itty bit of unwind
87            trickery in that the CFA *has* changed.  There is no easy way
88            to describe it correctly on entry to the function.  Fortunately,
89            it doesn't matter too much since at all points we can correctly
90            unwind back to ffi_call.  Note that the location to which we
91            moved the return address is (the new) CFA-4, so from the
92            perspective of the unwind info, it hasn't moved.  */
93         movl    %ecx, %ebp
94         cfi_def_cfa(%ebp, 8)
95         cfi_rel_offset(%ebp, 0)
96
97         movl    %edx, %esp              /* set outgoing argument stack */
98         movl    20+R_EAX*4(%ebp), %eax  /* set register arguments */
99         movl    20+R_EDX*4(%ebp), %edx
100         movl    20+R_ECX*4(%ebp), %ecx
101
102         call    *8(%ebp)
103
104         movl    12(%ebp), %ecx          /* load return type code */
105         movl    %ebx, 8(%ebp)           /* preserve %ebx */
106         cfi_rel_offset(%ebp, 8)
107
108         andl    $X86_RET_TYPE_MASK, %ecx
109 #ifdef __PIC__
110         call    __x86.get_pc_thunk.bx
111 1:      leal    0f-1b(%ebx, %ecx, 8), %ebx
112 #else
113         leal    0f(,%ecx, 8), %ebx
114 #endif
115         movl    16(%ebp), %ecx          /* load result address */
116         jmp     *%ebx
117
118         .align  8
119 0:
120 E(X86_RET_FLOAT)
121         fstps   (%ecx)
122         jmp     9f
123 E(X86_RET_DOUBLE)
124         fstpl   (%ecx)
125         jmp     9f
126 E(X86_RET_LDOUBLE)
127         fstpt   (%ecx)
128         jmp     9f
129 E(X86_RET_SINT8)
130         movsbl  %al, %eax
131         mov     %eax, (%ecx)
132         jmp     9f
133 E(X86_RET_SINT16)
134         movswl  %ax, %eax
135         mov     %eax, (%ecx)
136         jmp     9f
137 E(X86_RET_UINT8)
138         movzbl  %al, %eax
139         mov     %eax, (%ecx)
140         jmp     9f
141 E(X86_RET_UINT16)
142         movzwl  %ax, %eax
143         mov     %eax, (%ecx)
144         jmp     9f
145 E(X86_RET_INT64)
146         movl    %edx, 4(%ecx)
147         /* fallthru */
148 E(X86_RET_INT32)
149         movl    %eax, (%ecx)
150         /* fallthru */
151 E(X86_RET_VOID)
152 9:      movl    8(%ebp), %ebx
153         movl    %ebp, %esp
154         popl    %ebp
155         cfi_remember_state
156         cfi_def_cfa(%esp, 4)
157         cfi_restore(%ebx)
158         cfi_restore(%ebp)
159         ret
160         cfi_restore_state
161
162 E(X86_RET_STRUCTPOP)
163         jmp     9b
164 E(X86_RET_STRUCTARG)
165         jmp     9b
166 E(X86_RET_STRUCT_1B)
167         movb    %al, (%ecx)
168         jmp     9b
169 E(X86_RET_STRUCT_2B)
170         movw    %ax, (%ecx)
171         jmp     9b
172
173         /* Fill out the table so that bad values are predictable.  */
174 E(X86_RET_UNUSED14)
175         ud2
176 E(X86_RET_UNUSED15)
177         ud2
178
179         cfi_endproc
180 ENDF(ffi_call_i386)
181
182 /* The inner helper is declared as
183
184    void ffi_closure_inner(struct closure_frame *frame, char *argp)
185         __attribute_((fastcall))
186
187    Thus the arguments are placed in
188
189         ecx:    frame
190         edx:    argp
191 */
192
193 /* Macros to help setting up the closure_data structure.  */
194
195 #define closure_FS      (16 + 3*4 + 3*4 + 4)
196
197 .macro  FFI_CLOSURE_SAVE_REGS
198         movl    %eax, 16+R_EAX*4(%esp)
199         movl    %edx, 16+R_EDX*4(%esp)
200         movl    %ecx, 16+R_ECX*4(%esp)
201 .endm
202
203 .macro  FFI_CLOSURE_COPY_TRAMP_DATA chain
204         movl    FFI_TRAMPOLINE_SIZE(%eax), %edx         /* copy cif */
205         movl    FFI_TRAMPOLINE_SIZE+4(%eax), %ecx       /* copy fun */
206         movl    FFI_TRAMPOLINE_SIZE+8(%eax), %eax       /* copy user_data */
207         movl    %edx, 28(%esp)
208         movl    %ecx, 32(%esp)
209         movl    %eax, 36(%esp)
210 .endm
211
212 .macro  FFI_CLOSURE_CALL_INNER
213         movl    %esp, %ecx                      /* load closure_data */
214         leal    closure_FS+4(%esp), %edx        /* load incoming stack */
215 #ifdef __PIC__
216         movl    %ebx, 40(%esp)                  /* save ebx */
217         cfi_rel_offset(%ebx, 40)
218         call    __x86.get_pc_thunk.bx           /* load got register */
219         addl    $C(_GLOBAL_OFFSET_TABLE_), %ebx
220 #endif
221 #if defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE || !defined __PIC__
222         call    ffi_closure_inner
223 #else
224         call    ffi_closure_inner@PLT
225 #endif
226 .endm
227
228 .macro  FFI_CLOSURE_MASK_AND_JUMP
229         andl    $X86_RET_TYPE_MASK, %eax
230 #ifdef __PIC__
231         leal    0f@GOTOFF(%ebx, %eax, 8), %eax
232         movl    40(%esp), %ebx                  /* restore ebx */
233         cfi_restore(%ebx)
234 #else
235         leal    0f(, %eax, 8), %eax
236 #endif
237         jmp     *%eax
238 .endm
239
240 .macro  FFI_GO_CLOSURE suffix, chain, t1, t2
241         .align  16
242         .globl  C(ffi_go_closure_\suffix)
243         FFI_HIDDEN(C(ffi_go_closure_\suffix))
244 C(ffi_go_closure_\suffix):
245         cfi_startproc
246         subl    $closure_FS, %esp
247         cfi_adjust_cfa_offset(closure_FS)
248         FFI_CLOSURE_SAVE_REGS
249         movl    4(\chain), \t1          /* copy cif */
250         movl    8(\chain), \t2          /* copy fun */
251         movl    \t1, 28(%esp)
252         movl    \t2, 32(%esp)
253         movl    \chain, 36(%esp)        /* closure is user_data */
254         jmp     88f
255         cfi_endproc
256 ENDF(C(ffi_go_closure_\suffix))
257 .endm
258
259 FFI_GO_CLOSURE EAX, %eax, %edx, %ecx
260 FFI_GO_CLOSURE ECX, %ecx, %edx, %eax
261
262 /* The closure entry points are reached from the ffi_closure trampoline.
263    On entry, %eax contains the address of the ffi_closure.  */
264
265         .align  16
266         .globl  C(ffi_closure_i386)
267         FFI_HIDDEN(C(ffi_closure_i386))
268
269 C(ffi_closure_i386):
270         cfi_startproc
271         subl    $closure_FS, %esp
272         cfi_adjust_cfa_offset(closure_FS)
273
274         FFI_CLOSURE_SAVE_REGS
275         FFI_CLOSURE_COPY_TRAMP_DATA
276
277 88:     /* Entry point from preceeding Go closures.  */
278
279         FFI_CLOSURE_CALL_INNER
280         FFI_CLOSURE_MASK_AND_JUMP
281
282         .align  8
283 0:
284 E(X86_RET_FLOAT)
285         flds    (%esp)
286         jmp     9f
287 E(X86_RET_DOUBLE)
288         fldl    (%esp)
289         jmp     9f
290 E(X86_RET_LDOUBLE)
291         fldt    (%esp)
292         jmp     9f
293 E(X86_RET_SINT8)
294         movsbl  (%esp), %eax
295         jmp     9f
296 E(X86_RET_SINT16)
297         movswl  (%esp), %eax
298         jmp     9f
299 E(X86_RET_UINT8)
300         movzbl  (%esp), %eax
301         jmp     9f
302 E(X86_RET_UINT16)
303         movzwl  (%esp), %eax
304         jmp     9f
305 E(X86_RET_INT64)
306         movl    4(%esp), %edx
307         /* fallthru */
308 E(X86_RET_INT32)
309         movl    (%esp), %eax
310         /* fallthru */
311 E(X86_RET_VOID)
312 9:      addl    $closure_FS, %esp
313         cfi_adjust_cfa_offset(-closure_FS)
314         ret
315         cfi_adjust_cfa_offset(closure_FS)
316 E(X86_RET_STRUCTPOP)
317         addl    $closure_FS, %esp
318         cfi_adjust_cfa_offset(-closure_FS)
319         ret     $4
320         cfi_adjust_cfa_offset(closure_FS)
321 E(X86_RET_STRUCTARG)
322         movl    (%esp), %eax
323         jmp     9b
324 E(X86_RET_STRUCT_1B)
325         movzbl  (%esp), %eax
326         jmp     9b
327 E(X86_RET_STRUCT_2B)
328         movzwl  (%esp), %eax
329         jmp     9b
330
331         /* Fill out the table so that bad values are predictable.  */
332 E(X86_RET_UNUSED14)
333         ud2
334 E(X86_RET_UNUSED15)
335         ud2
336
337         cfi_endproc
338 ENDF(C(ffi_closure_i386))
339
340 FFI_GO_CLOSURE STDCALL, %ecx, %edx, %eax
341
342 /* For REGISTER, we have no available parameter registers, and so we
343    enter here having pushed the closure onto the stack.  */
344
345         .align  16
346         .globl  C(ffi_closure_REGISTER)
347         FFI_HIDDEN(C(ffi_closure_REGISTER))
348 C(ffi_closure_REGISTER):
349         cfi_startproc
350         cfi_def_cfa(%esp, 8)
351         cfi_offset(%eip, -8)
352         subl    $closure_FS-4, %esp
353         cfi_adjust_cfa_offset(closure_FS-4)
354
355         FFI_CLOSURE_SAVE_REGS
356
357         movl    closure_FS-4(%esp), %ecx        /* load retaddr */
358         movl    closure_FS(%esp), %eax          /* load closure */
359         movl    %ecx, closure_FS(%esp)          /* move retaddr */
360         jmp     0f
361
362         cfi_endproc
363 ENDF(C(ffi_closure_REGISTER))
364
365 /* For STDCALL (and others), we need to pop N bytes of arguments off
366    the stack following the closure.  The amount needing to be popped
367    is returned to us from ffi_closure_inner.  */
368
369         .align  16
370         .globl  C(ffi_closure_STDCALL)
371         FFI_HIDDEN(C(ffi_closure_STDCALL))
372 C(ffi_closure_STDCALL):
373         cfi_startproc
374         subl    $closure_FS, %esp
375         cfi_adjust_cfa_offset(closure_FS)
376
377         FFI_CLOSURE_SAVE_REGS
378
379 0:      /* Entry point from ffi_closure_REGISTER.  */
380
381         FFI_CLOSURE_COPY_TRAMP_DATA
382
383 88:     /* Entry point from preceeding Go closure.  */
384
385         FFI_CLOSURE_CALL_INNER
386
387         movl    %eax, %ecx
388         shrl    $X86_RET_POP_SHIFT, %ecx        /* isolate pop count */
389         leal    closure_FS(%esp, %ecx), %ecx    /* compute popped esp */
390         movl    closure_FS(%esp), %edx          /* move return address */
391         movl    %edx, (%ecx)
392
393         /* New pseudo-stack frame based off ecx.  This is unwind trickery
394            in that the CFA *has* changed, to the proper popped stack address.
395            Note that the location to which we moved the return address
396            is the new CFA-4, so that's unchanged.  */
397         cfi_def_cfa(%ecx, 4)
398         /* Normally esp is unwound to CFA + the caller's ARGS_SIZE.
399            We've just set the CFA to that final value.  Tell the unwinder
400            to restore esp from CFA without the ARGS_SIZE:
401            DW_CFA_val_expression %esp, DW_OP_call_frame_cfa.  */
402         cfi_escape(0x16, 4, 1, 0x9c)
403
404         FFI_CLOSURE_MASK_AND_JUMP
405
406         .align  8
407 0:
408 E(X86_RET_FLOAT)
409         flds    (%esp)
410         movl    %ecx, %esp
411         ret
412 E(X86_RET_DOUBLE)
413         fldl    (%esp)
414         movl    %ecx, %esp
415         ret
416 E(X86_RET_LDOUBLE)
417         fldt    (%esp)
418         movl    %ecx, %esp
419         ret
420 E(X86_RET_SINT8)
421         movsbl  (%esp), %eax
422         movl    %ecx, %esp
423         ret
424 E(X86_RET_SINT16)
425         movswl  (%esp), %eax
426         movl    %ecx, %esp
427         ret
428 E(X86_RET_UINT8)
429         movzbl  (%esp), %eax
430         movl    %ecx, %esp
431         ret
432 E(X86_RET_UINT16)
433         movzwl  (%esp), %eax
434         movl    %ecx, %esp
435         ret
436 E(X86_RET_INT64)
437         popl    %eax
438         popl    %edx
439         movl    %ecx, %esp
440         ret
441 E(X86_RET_INT32)
442         movl    (%esp), %eax
443         movl    %ecx, %esp
444         ret
445 E(X86_RET_VOID)
446         movl    %ecx, %esp
447         ret
448 E(X86_RET_STRUCTPOP)
449         movl    %ecx, %esp
450         ret
451 E(X86_RET_STRUCTARG)
452         movl    (%esp), %eax
453         movl    %ecx, %esp
454         ret
455 E(X86_RET_STRUCT_1B)
456         movzbl  (%esp), %eax
457         movl    %ecx, %esp
458         ret
459 E(X86_RET_STRUCT_2B)
460         movzwl  (%esp), %eax
461         movl    %ecx, %esp
462         ret
463
464         /* Fill out the table so that bad values are predictable.  */
465 E(X86_RET_UNUSED14)
466         ud2
467 E(X86_RET_UNUSED15)
468         ud2
469
470         cfi_endproc
471 ENDF(C(ffi_closure_STDCALL))
472
473 #if !FFI_NO_RAW_API
474
475 #define raw_closure_S_FS        (16+16+12)
476
477         .align  16
478         .globl  C(ffi_closure_raw_SYSV)
479         FFI_HIDDEN(C(ffi_closure_raw_SYSV))
480 C(ffi_closure_raw_SYSV):
481         cfi_startproc
482         subl    $raw_closure_S_FS, %esp
483         cfi_adjust_cfa_offset(raw_closure_S_FS)
484         movl    %ebx, raw_closure_S_FS-4(%esp)
485         cfi_rel_offset(%ebx, raw_closure_S_FS-4)
486
487         movl    FFI_TRAMPOLINE_SIZE+8(%eax), %edx       /* load cl->user_data */
488         movl    %edx, 12(%esp)
489         leal    raw_closure_S_FS+4(%esp), %edx          /* load raw_args */
490         movl    %edx, 8(%esp)
491         leal    16(%esp), %edx                          /* load &res */
492         movl    %edx, 4(%esp)
493         movl    FFI_TRAMPOLINE_SIZE(%eax), %ebx         /* load cl->cif */
494         movl    %ebx, (%esp)
495         call    *FFI_TRAMPOLINE_SIZE+4(%eax)            /* call cl->fun */
496
497         movl    20(%ebx), %eax                          /* load cif->flags */
498         andl    $X86_RET_TYPE_MASK, %eax
499 #ifdef __PIC__
500         call    __x86.get_pc_thunk.bx
501 1:      leal    0f-1b(%ebx, %eax, 8), %eax
502 #else
503         leal    0f(,%eax, 8), %eax
504 #endif
505         movl    raw_closure_S_FS-4(%esp), %ebx
506         cfi_restore(%ebx)
507         jmp     *%eax
508
509         .align  8
510 0:
511 E(X86_RET_FLOAT)
512         flds    16(%esp)
513         jmp     9f
514 E(X86_RET_DOUBLE)
515         fldl    16(%esp)
516         jmp     9f
517 E(X86_RET_LDOUBLE)
518         fldt    16(%esp)
519         jmp     9f
520 E(X86_RET_SINT8)
521         movsbl  16(%esp), %eax
522         jmp     9f
523 E(X86_RET_SINT16)
524         movswl  16(%esp), %eax
525         jmp     9f
526 E(X86_RET_UINT8)
527         movzbl  16(%esp), %eax
528         jmp     9f
529 E(X86_RET_UINT16)
530         movzwl  16(%esp), %eax
531         jmp     9f
532 E(X86_RET_INT64)
533         movl    16+4(%esp), %edx
534         /* fallthru */
535 E(X86_RET_INT32)
536         movl    16(%esp), %eax
537         /* fallthru */
538 E(X86_RET_VOID)
539 9:      addl    $raw_closure_S_FS, %esp
540         cfi_adjust_cfa_offset(-raw_closure_S_FS)
541         ret
542         cfi_adjust_cfa_offset(raw_closure_S_FS)
543 E(X86_RET_STRUCTPOP)
544         addl    $raw_closure_S_FS, %esp
545         cfi_adjust_cfa_offset(-raw_closure_S_FS)
546         ret     $4
547         cfi_adjust_cfa_offset(raw_closure_S_FS)
548 E(X86_RET_STRUCTARG)
549         movl    16(%esp), %eax
550         jmp     9b
551 E(X86_RET_STRUCT_1B)
552         movzbl  16(%esp), %eax
553         jmp     9b
554 E(X86_RET_STRUCT_2B)
555         movzwl  16(%esp), %eax
556         jmp     9b
557
558         /* Fill out the table so that bad values are predictable.  */
559 E(X86_RET_UNUSED14)
560         ud2
561 E(X86_RET_UNUSED15)
562         ud2
563
564         cfi_endproc
565 ENDF(C(ffi_closure_raw_SYSV))
566
567 #undef  raw_closure_S_FS
568 #define raw_closure_T_FS        (16+16+8)
569
570         .align  16
571         .globl  C(ffi_closure_raw_THISCALL)
572         FFI_HIDDEN(C(ffi_closure_raw_THISCALL))
573 C(ffi_closure_raw_THISCALL):
574         cfi_startproc
575         /* Rearrange the stack such that %ecx is the first argument.
576            This means moving the return address.  */
577         popl    %edx
578         cfi_adjust_cfa_offset(-4)
579         cfi_register(%eip, %edx)
580         pushl   %ecx
581         cfi_adjust_cfa_offset(4)
582         pushl   %edx
583         cfi_adjust_cfa_offset(4)
584         cfi_rel_offset(%eip, 0)
585         subl    $raw_closure_T_FS, %esp
586         cfi_adjust_cfa_offset(raw_closure_T_FS)
587         movl    %ebx, raw_closure_T_FS-4(%esp)
588         cfi_offset(%ebx, raw_closure_T_FS-4)
589
590         movl    FFI_TRAMPOLINE_SIZE+8(%eax), %edx       /* load cl->user_data */
591         movl    %edx, 12(%esp)
592         leal    raw_closure_T_FS+4(%esp), %edx          /* load raw_args */
593         movl    %edx, 8(%esp)
594         leal    16(%esp), %edx                          /* load &res */
595         movl    %edx, 4(%esp)
596         movl    FFI_TRAMPOLINE_SIZE(%eax), %ebx         /* load cl->cif */
597         movl    %ebx, (%esp)
598         call    *FFI_TRAMPOLINE_SIZE+4(%eax)            /* call cl->fun */
599
600         movl    20(%ebx), %eax                          /* load cif->flags */
601         andl    $X86_RET_TYPE_MASK, %eax
602 #ifdef __PIC__
603         call    __x86.get_pc_thunk.bx
604 1:      leal    0f-1b(%ebx, %eax, 8), %eax
605 #else
606         leal    0f(,%eax, 8), %eax
607 #endif
608         movl    raw_closure_T_FS-4(%esp), %ebx
609         cfi_restore(%ebx)
610         jmp     *%eax
611
612         .align  8
613 0:
614 E(X86_RET_FLOAT)
615         flds    16(%esp)
616         jmp     9f
617 E(X86_RET_DOUBLE)
618         fldl    16(%esp)
619         jmp     9f
620 E(X86_RET_LDOUBLE)
621         fldt    16(%esp)
622         jmp     9f
623 E(X86_RET_SINT8)
624         movsbl  16(%esp), %eax
625         jmp     9f
626 E(X86_RET_SINT16)
627         movswl  16(%esp), %eax
628         jmp     9f
629 E(X86_RET_UINT8)
630         movzbl  16(%esp), %eax
631         jmp     9f
632 E(X86_RET_UINT16)
633         movzwl  16(%esp), %eax
634         jmp     9f
635 E(X86_RET_INT64)
636         movl    16+4(%esp), %edx
637         /* fallthru */
638 E(X86_RET_INT32)
639         movl    16(%esp), %eax
640         /* fallthru */
641 E(X86_RET_VOID)
642 9:      addl    $raw_closure_T_FS, %esp
643         cfi_adjust_cfa_offset(-raw_closure_T_FS)
644         /* Remove the extra %ecx argument we pushed.  */
645         ret     $4
646         cfi_adjust_cfa_offset(raw_closure_T_FS)
647 E(X86_RET_STRUCTPOP)
648         addl    $raw_closure_T_FS, %esp
649         cfi_adjust_cfa_offset(-raw_closure_T_FS)
650         ret     $8
651         cfi_adjust_cfa_offset(raw_closure_T_FS)
652 E(X86_RET_STRUCTARG)
653         movl    16(%esp), %eax
654         jmp     9b
655 E(X86_RET_STRUCT_1B)
656         movzbl  16(%esp), %eax
657         jmp     9b
658 E(X86_RET_STRUCT_2B)
659         movzwl  16(%esp), %eax
660         jmp     9b
661
662         /* Fill out the table so that bad values are predictable.  */
663 E(X86_RET_UNUSED14)
664         ud2
665 E(X86_RET_UNUSED15)
666         ud2
667
668         cfi_endproc
669 ENDF(C(ffi_closure_raw_THISCALL))
670
671 #endif /* !FFI_NO_RAW_API */
672
673 #if defined(__PIC__)
674         .section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
675         .globl  __x86.get_pc_thunk.bx
676         .hidden __x86.get_pc_thunk.bx
677         .type   __x86.get_pc_thunk.bx,@function
678 __x86.get_pc_thunk.bx:
679         cfi_startproc
680         movl    (%esp), %ebx
681         ret
682         cfi_endproc
683         .size   __x86.get_pc_thunk.bx, . - __x86.get_pc_thunk.bx
684 #endif /* __PIC__ */
685
686 #endif /* ifndef __x86_64__ */
687 #if defined __ELF__ && defined __linux__
688         .section        .note.GNU-stack,"",@progbits
689 #endif