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