Static tramp v5 (#624)
[platform/upstream/libffi.git] / src / x86 / unix64.S
1 /* -----------------------------------------------------------------------
2    unix64.S - Copyright (c) 2013  The Written Word, Inc.
3             - Copyright (c) 2008  Red Hat, Inc
4             - Copyright (c) 2002  Bo Thorsen <bo@suse.de>
5
6    x86-64 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 __x86_64__
30 #define LIBFFI_ASM      
31 #include <fficonfig.h>
32 #include <ffi.h>
33 #include "internal64.h"
34 #include "asmnames.h"
35
36         .text
37
38 /* This macro allows the safe creation of jump tables without an
39    actual table.  The entry points into the table are all 8 bytes.
40    The use of ORG asserts that we're at the correct location.  */
41 /* ??? The clang assembler doesn't handle .org with symbolic expressions.  */
42 #if defined(__clang__) || defined(__APPLE__) || (defined (__sun__) && defined(__svr4__))
43 # define E(BASE, X)     .balign 8
44 #else
45 # ifdef __CET__
46 #  define E(BASE, X)    .balign 8; .org BASE + X * 16
47 # else
48 #  define E(BASE, X)    .balign 8; .org BASE + X * 8
49 # endif
50 #endif
51
52 /* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
53                     void *raddr, void (*fnaddr)(void));
54
55    Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
56    for this function.  This has been allocated by ffi_call.  We also
57    deallocate some of the stack that has been alloca'd.  */
58
59         .balign 8
60         .globl  C(ffi_call_unix64)
61         FFI_HIDDEN(C(ffi_call_unix64))
62
63 C(ffi_call_unix64):
64 L(UW0):
65         _CET_ENDBR
66         movq    (%rsp), %r10            /* Load return address.  */
67         leaq    (%rdi, %rsi), %rax      /* Find local stack base.  */
68         movq    %rdx, (%rax)            /* Save flags.  */
69         movq    %rcx, 8(%rax)           /* Save raddr.  */
70         movq    %rbp, 16(%rax)          /* Save old frame pointer.  */
71         movq    %r10, 24(%rax)          /* Relocate return address.  */
72         movq    %rax, %rbp              /* Finalize local stack frame.  */
73
74         /* New stack frame based off rbp.  This is a itty bit of unwind
75            trickery in that the CFA *has* changed.  There is no easy way
76            to describe it correctly on entry to the function.  Fortunately,
77            it doesn't matter too much since at all points we can correctly
78            unwind back to ffi_call.  Note that the location to which we
79            moved the return address is (the new) CFA-8, so from the
80            perspective of the unwind info, it hasn't moved.  */
81 L(UW1):
82         /* cfi_def_cfa(%rbp, 32) */
83         /* cfi_rel_offset(%rbp, 16) */
84
85         movq    %rdi, %r10              /* Save a copy of the register area. */
86         movq    %r8, %r11               /* Save a copy of the target fn.  */
87
88         /* Load up all argument registers.  */
89         movq    (%r10), %rdi
90         movq    0x08(%r10), %rsi
91         movq    0x10(%r10), %rdx
92         movq    0x18(%r10), %rcx
93         movq    0x20(%r10), %r8
94         movq    0x28(%r10), %r9
95         movl    0xb0(%r10), %eax        /* Set number of SSE registers.  */
96         testl   %eax, %eax
97         jnz     L(load_sse)
98 L(ret_from_load_sse):
99
100         /* Deallocate the reg arg area, except for r10, then load via pop.  */
101         leaq    0xb8(%r10), %rsp
102         popq    %r10
103
104         /* Call the user function.  */
105         call    *%r11
106
107         /* Deallocate stack arg area; local stack frame in redzone.  */
108         leaq    24(%rbp), %rsp
109
110         movq    0(%rbp), %rcx           /* Reload flags.  */
111         movq    8(%rbp), %rdi           /* Reload raddr.  */
112         movq    16(%rbp), %rbp          /* Reload old frame pointer.  */
113 L(UW2):
114         /* cfi_remember_state */
115         /* cfi_def_cfa(%rsp, 8) */
116         /* cfi_restore(%rbp) */
117
118         /* The first byte of the flags contains the FFI_TYPE.  */
119         cmpb    $UNIX64_RET_LAST, %cl
120         movzbl  %cl, %r10d
121         leaq    L(store_table)(%rip), %r11
122         ja      L(sa)
123 #ifdef __CET__
124         /* NB: Originally, each slot is 8 byte.  4 bytes of ENDBR64 +
125            4 bytes NOP padding double slot size to 16 bytes.  */
126         addl    %r10d, %r10d
127 #endif
128         leaq    (%r11, %r10, 8), %r10
129
130         /* Prep for the structure cases: scratch area in redzone.  */
131         leaq    -20(%rsp), %rsi
132         jmp     *%r10
133
134         .balign 8
135 L(store_table):
136 E(L(store_table), UNIX64_RET_VOID)
137         _CET_ENDBR
138         ret
139 E(L(store_table), UNIX64_RET_UINT8)
140         _CET_ENDBR
141         movzbl  %al, %eax
142         movq    %rax, (%rdi)
143         ret
144 E(L(store_table), UNIX64_RET_UINT16)
145         _CET_ENDBR
146         movzwl  %ax, %eax
147         movq    %rax, (%rdi)
148         ret
149 E(L(store_table), UNIX64_RET_UINT32)
150         _CET_ENDBR
151         movl    %eax, %eax
152         movq    %rax, (%rdi)
153         ret
154 E(L(store_table), UNIX64_RET_SINT8)
155         _CET_ENDBR
156         movsbq  %al, %rax
157         movq    %rax, (%rdi)
158         ret
159 E(L(store_table), UNIX64_RET_SINT16)
160         _CET_ENDBR
161         movswq  %ax, %rax
162         movq    %rax, (%rdi)
163         ret
164 E(L(store_table), UNIX64_RET_SINT32)
165         _CET_ENDBR
166         cltq
167         movq    %rax, (%rdi)
168         ret
169 E(L(store_table), UNIX64_RET_INT64)
170         _CET_ENDBR
171         movq    %rax, (%rdi)
172         ret
173 E(L(store_table), UNIX64_RET_XMM32)
174         _CET_ENDBR
175         movd    %xmm0, (%rdi)
176         ret
177 E(L(store_table), UNIX64_RET_XMM64)
178         _CET_ENDBR
179         movq    %xmm0, (%rdi)
180         ret
181 E(L(store_table), UNIX64_RET_X87)
182         _CET_ENDBR
183         fstpt   (%rdi)
184         ret
185 E(L(store_table), UNIX64_RET_X87_2)
186         _CET_ENDBR
187         fstpt   (%rdi)
188         fstpt   16(%rdi)
189         ret
190 E(L(store_table), UNIX64_RET_ST_XMM0_RAX)
191         _CET_ENDBR
192         movq    %rax, 8(%rsi)
193         jmp     L(s3)
194 E(L(store_table), UNIX64_RET_ST_RAX_XMM0)
195         _CET_ENDBR
196         movq    %xmm0, 8(%rsi)
197         jmp     L(s2)
198 E(L(store_table), UNIX64_RET_ST_XMM0_XMM1)
199         _CET_ENDBR
200         movq    %xmm1, 8(%rsi)
201         jmp     L(s3)
202 E(L(store_table), UNIX64_RET_ST_RAX_RDX)
203         _CET_ENDBR
204         movq    %rdx, 8(%rsi)
205 L(s2):
206         movq    %rax, (%rsi)
207         shrl    $UNIX64_SIZE_SHIFT, %ecx
208         rep movsb
209         ret
210         .balign 8
211 L(s3):
212         movq    %xmm0, (%rsi)
213         shrl    $UNIX64_SIZE_SHIFT, %ecx
214         rep movsb
215         ret
216
217 L(sa):  call    PLT(C(abort))
218
219         /* Many times we can avoid loading any SSE registers at all.
220            It's not worth an indirect jump to load the exact set of
221            SSE registers needed; zero or all is a good compromise.  */
222         .balign 2
223 L(UW3):
224         /* cfi_restore_state */
225 L(load_sse):
226         movdqa  0x30(%r10), %xmm0
227         movdqa  0x40(%r10), %xmm1
228         movdqa  0x50(%r10), %xmm2
229         movdqa  0x60(%r10), %xmm3
230         movdqa  0x70(%r10), %xmm4
231         movdqa  0x80(%r10), %xmm5
232         movdqa  0x90(%r10), %xmm6
233         movdqa  0xa0(%r10), %xmm7
234         jmp     L(ret_from_load_sse)
235
236 L(UW4):
237 ENDF(C(ffi_call_unix64))
238
239 /* 6 general registers, 8 vector registers,
240    32 bytes of rvalue, 8 bytes of alignment.  */
241 #define ffi_closure_OFS_G       0
242 #define ffi_closure_OFS_V       (6*8)
243 #define ffi_closure_OFS_RVALUE  (ffi_closure_OFS_V + 8*16)
244 #define ffi_closure_FS          (ffi_closure_OFS_RVALUE + 32 + 8)
245
246 /* The location of rvalue within the red zone after deallocating the frame.  */
247 #define ffi_closure_RED_RVALUE  (ffi_closure_OFS_RVALUE - ffi_closure_FS)
248
249         .balign 2
250         .globl  C(ffi_closure_unix64_sse)
251         FFI_HIDDEN(C(ffi_closure_unix64_sse))
252
253 C(ffi_closure_unix64_sse):
254 L(UW5):
255         _CET_ENDBR
256         subq    $ffi_closure_FS, %rsp
257 L(UW6):
258         /* cfi_adjust_cfa_offset(ffi_closure_FS) */
259
260         movdqa  %xmm0, ffi_closure_OFS_V+0x00(%rsp)
261         movdqa  %xmm1, ffi_closure_OFS_V+0x10(%rsp)
262         movdqa  %xmm2, ffi_closure_OFS_V+0x20(%rsp)
263         movdqa  %xmm3, ffi_closure_OFS_V+0x30(%rsp)
264         movdqa  %xmm4, ffi_closure_OFS_V+0x40(%rsp)
265         movdqa  %xmm5, ffi_closure_OFS_V+0x50(%rsp)
266         movdqa  %xmm6, ffi_closure_OFS_V+0x60(%rsp)
267         movdqa  %xmm7, ffi_closure_OFS_V+0x70(%rsp)
268         jmp     L(sse_entry1)
269
270 L(UW7):
271 ENDF(C(ffi_closure_unix64_sse))
272
273         .balign 2
274         .globl  C(ffi_closure_unix64)
275         FFI_HIDDEN(C(ffi_closure_unix64))
276
277 C(ffi_closure_unix64):
278 L(UW8):
279         _CET_ENDBR
280         subq    $ffi_closure_FS, %rsp
281 L(UW9):
282         /* cfi_adjust_cfa_offset(ffi_closure_FS) */
283 L(sse_entry1):
284         movq    %rdi, ffi_closure_OFS_G+0x00(%rsp)
285         movq    %rsi, ffi_closure_OFS_G+0x08(%rsp)
286         movq    %rdx, ffi_closure_OFS_G+0x10(%rsp)
287         movq    %rcx, ffi_closure_OFS_G+0x18(%rsp)
288         movq    %r8,  ffi_closure_OFS_G+0x20(%rsp)
289         movq    %r9,  ffi_closure_OFS_G+0x28(%rsp)
290
291 #ifdef __ILP32__
292         movl    FFI_TRAMPOLINE_SIZE(%r10), %edi         /* Load cif */
293         movl    FFI_TRAMPOLINE_SIZE+4(%r10), %esi       /* Load fun */
294         movl    FFI_TRAMPOLINE_SIZE+8(%r10), %edx       /* Load user_data */
295 #else
296         movq    FFI_TRAMPOLINE_SIZE(%r10), %rdi         /* Load cif */
297         movq    FFI_TRAMPOLINE_SIZE+8(%r10), %rsi       /* Load fun */
298         movq    FFI_TRAMPOLINE_SIZE+16(%r10), %rdx      /* Load user_data */
299 #endif
300 L(do_closure):
301         leaq    ffi_closure_OFS_RVALUE(%rsp), %rcx      /* Load rvalue */
302         movq    %rsp, %r8                               /* Load reg_args */
303         leaq    ffi_closure_FS+8(%rsp), %r9             /* Load argp */
304         call    PLT(C(ffi_closure_unix64_inner))
305
306         /* Deallocate stack frame early; return value is now in redzone.  */
307         addq    $ffi_closure_FS, %rsp
308 L(UW10):
309         /* cfi_adjust_cfa_offset(-ffi_closure_FS) */
310
311         /* The first byte of the return value contains the FFI_TYPE.  */
312         cmpb    $UNIX64_RET_LAST, %al
313         movzbl  %al, %r10d
314         leaq    L(load_table)(%rip), %r11
315         ja      L(la)
316 #ifdef __CET__
317         /* NB: Originally, each slot is 8 byte.  4 bytes of ENDBR64 +
318            4 bytes NOP padding double slot size to 16 bytes.  */
319         addl    %r10d, %r10d
320 #endif
321         leaq    (%r11, %r10, 8), %r10
322         leaq    ffi_closure_RED_RVALUE(%rsp), %rsi
323         jmp     *%r10
324
325         .balign 8
326 L(load_table):
327 E(L(load_table), UNIX64_RET_VOID)
328         _CET_ENDBR
329         ret
330 E(L(load_table), UNIX64_RET_UINT8)
331         _CET_ENDBR
332         movzbl  (%rsi), %eax
333         ret
334 E(L(load_table), UNIX64_RET_UINT16)
335         _CET_ENDBR
336         movzwl  (%rsi), %eax
337         ret
338 E(L(load_table), UNIX64_RET_UINT32)
339         _CET_ENDBR
340         movl    (%rsi), %eax
341         ret
342 E(L(load_table), UNIX64_RET_SINT8)
343         _CET_ENDBR
344         movsbl  (%rsi), %eax
345         ret
346 E(L(load_table), UNIX64_RET_SINT16)
347         _CET_ENDBR
348         movswl  (%rsi), %eax
349         ret
350 E(L(load_table), UNIX64_RET_SINT32)
351         _CET_ENDBR
352         movl    (%rsi), %eax
353         ret
354 E(L(load_table), UNIX64_RET_INT64)
355         _CET_ENDBR
356         movq    (%rsi), %rax
357         ret
358 E(L(load_table), UNIX64_RET_XMM32)
359         _CET_ENDBR
360         movd    (%rsi), %xmm0
361         ret
362 E(L(load_table), UNIX64_RET_XMM64)
363         _CET_ENDBR
364         movq    (%rsi), %xmm0
365         ret
366 E(L(load_table), UNIX64_RET_X87)
367         _CET_ENDBR
368         fldt    (%rsi)
369         ret
370 E(L(load_table), UNIX64_RET_X87_2)
371         _CET_ENDBR
372         fldt    16(%rsi)
373         fldt    (%rsi)
374         ret
375 E(L(load_table), UNIX64_RET_ST_XMM0_RAX)
376         _CET_ENDBR
377         movq    8(%rsi), %rax
378         jmp     L(l3)
379 E(L(load_table), UNIX64_RET_ST_RAX_XMM0)
380         _CET_ENDBR
381         movq    8(%rsi), %xmm0
382         jmp     L(l2)
383 E(L(load_table), UNIX64_RET_ST_XMM0_XMM1)
384         _CET_ENDBR
385         movq    8(%rsi), %xmm1
386         jmp     L(l3)
387 E(L(load_table), UNIX64_RET_ST_RAX_RDX)
388         _CET_ENDBR
389         movq    8(%rsi), %rdx
390 L(l2):
391         movq    (%rsi), %rax
392         ret
393         .balign 8
394 L(l3):
395         movq    (%rsi), %xmm0
396         ret
397
398 L(la):  call    PLT(C(abort))
399
400 L(UW11):
401 ENDF(C(ffi_closure_unix64))
402
403         .balign 2
404         .globl  C(ffi_go_closure_unix64_sse)
405         FFI_HIDDEN(C(ffi_go_closure_unix64_sse))
406
407 C(ffi_go_closure_unix64_sse):
408 L(UW12):
409         _CET_ENDBR
410         subq    $ffi_closure_FS, %rsp
411 L(UW13):
412         /* cfi_adjust_cfa_offset(ffi_closure_FS) */
413
414         movdqa  %xmm0, ffi_closure_OFS_V+0x00(%rsp)
415         movdqa  %xmm1, ffi_closure_OFS_V+0x10(%rsp)
416         movdqa  %xmm2, ffi_closure_OFS_V+0x20(%rsp)
417         movdqa  %xmm3, ffi_closure_OFS_V+0x30(%rsp)
418         movdqa  %xmm4, ffi_closure_OFS_V+0x40(%rsp)
419         movdqa  %xmm5, ffi_closure_OFS_V+0x50(%rsp)
420         movdqa  %xmm6, ffi_closure_OFS_V+0x60(%rsp)
421         movdqa  %xmm7, ffi_closure_OFS_V+0x70(%rsp)
422         jmp     L(sse_entry2)
423
424 L(UW14):
425 ENDF(C(ffi_go_closure_unix64_sse))
426
427         .balign 2
428         .globl  C(ffi_go_closure_unix64)
429         FFI_HIDDEN(C(ffi_go_closure_unix64))
430
431 C(ffi_go_closure_unix64):
432 L(UW15):
433         _CET_ENDBR
434         subq    $ffi_closure_FS, %rsp
435 L(UW16):
436         /* cfi_adjust_cfa_offset(ffi_closure_FS) */
437 L(sse_entry2):
438         movq    %rdi, ffi_closure_OFS_G+0x00(%rsp)
439         movq    %rsi, ffi_closure_OFS_G+0x08(%rsp)
440         movq    %rdx, ffi_closure_OFS_G+0x10(%rsp)
441         movq    %rcx, ffi_closure_OFS_G+0x18(%rsp)
442         movq    %r8,  ffi_closure_OFS_G+0x20(%rsp)
443         movq    %r9,  ffi_closure_OFS_G+0x28(%rsp)
444
445 #ifdef __ILP32__
446         movl    4(%r10), %edi           /* Load cif */
447         movl    8(%r10), %esi           /* Load fun */
448         movl    %r10d, %edx             /* Load closure (user_data) */
449 #else
450         movq    8(%r10), %rdi           /* Load cif */
451         movq    16(%r10), %rsi          /* Load fun */
452         movq    %r10, %rdx              /* Load closure (user_data) */
453 #endif
454         jmp     L(do_closure)
455
456 L(UW17):
457 ENDF(C(ffi_go_closure_unix64))
458
459 #if defined(FFI_EXEC_STATIC_TRAMP)
460         .balign 8
461         .globl  C(ffi_closure_unix64_sse_alt)
462         FFI_HIDDEN(C(ffi_closure_unix64_sse_alt))
463
464 C(ffi_closure_unix64_sse_alt):
465         /* See the comments above trampoline_code_table. */
466         _CET_ENDBR
467         movq    8(%rsp), %r10                   /* Load closure in r10 */
468         addq    $16, %rsp                       /* Restore the stack */
469         jmp     C(ffi_closure_unix64_sse)
470 ENDF(C(ffi_closure_unix64_sse_alt))
471
472         .balign 8
473         .globl  C(ffi_closure_unix64_alt)
474         FFI_HIDDEN(C(ffi_closure_unix64_alt))
475
476 C(ffi_closure_unix64_alt):
477         /* See the comments above trampoline_code_table. */
478         _CET_ENDBR
479         movq    8(%rsp), %r10                   /* Load closure in r10 */
480         addq    $16, %rsp                       /* Restore the stack */
481         jmp     C(ffi_closure_unix64)
482         ENDF(C(ffi_closure_unix64_alt))
483
484 /*
485  * Below is the definition of the trampoline code table. Each element in
486  * the code table is a trampoline.
487  *
488  * Because we jump to the trampoline, we place a _CET_ENDBR at the
489  * beginning of the trampoline to mark it as a valid branch target. This is
490  * part of the the Intel CET (Control Flow Enforcement Technology).
491  */
492 /*
493  * The trampoline uses register r10. It saves the original value of r10 on
494  * the stack.
495  *
496  * The trampoline has two parameters - target code to jump to and data for
497  * the target code. The trampoline extracts the parameters from its parameter
498  * block (see tramp_table_map()). The trampoline saves the data address on
499  * the stack. Finally, it jumps to the target code.
500  *
501  * The target code can choose to:
502  *
503  * - restore the value of r10
504  * - load the data address in a register
505  * - restore the stack pointer to what it was when the trampoline was invoked.
506  */
507 #ifdef ENDBR_PRESENT
508 #define X86_DATA_OFFSET         4077
509 #define X86_CODE_OFFSET         4073
510 #else
511 #define X86_DATA_OFFSET         4081
512 #define X86_CODE_OFFSET         4077
513 #endif
514
515         .align  UNIX64_TRAMP_MAP_SIZE
516         .globl  trampoline_code_table
517         FFI_HIDDEN(C(trampoline_code_table))
518
519 C(trampoline_code_table):
520         .rept   UNIX64_TRAMP_MAP_SIZE / UNIX64_TRAMP_SIZE
521         _CET_ENDBR
522         subq    $16, %rsp                       /* Make space on the stack */
523         movq    %r10, (%rsp)                    /* Save %r10 on stack */
524         movq    X86_DATA_OFFSET(%rip), %r10     /* Copy data into %r10 */
525         movq    %r10, 8(%rsp)                   /* Save data on stack */
526         movq    X86_CODE_OFFSET(%rip), %r10     /* Copy code into %r10 */
527         jmp     *%r10                           /* Jump to code */
528         .align  8
529         .endr
530 ENDF(C(trampoline_code_table))
531         .align  UNIX64_TRAMP_MAP_SIZE
532 #endif /* FFI_EXEC_STATIC_TRAMP */
533
534 /* Sadly, OSX cctools-as doesn't understand .cfi directives at all.  */
535
536 #ifdef __APPLE__
537 .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
538 EHFrame0:
539 #elif defined(HAVE_AS_X86_64_UNWIND_SECTION_TYPE)
540 .section .eh_frame,"a",@unwind
541 #else
542 .section .eh_frame,"a",@progbits
543 #endif
544
545 #ifdef HAVE_AS_X86_PCREL
546 # define PCREL(X)       X - .
547 #else
548 # define PCREL(X)       X@rel
549 #endif
550
551 /* Simplify advancing between labels.  Assume DW_CFA_advance_loc1 fits.  */
552 #ifdef __CET__
553 /* Use DW_CFA_advance_loc2 when IBT is enabled.  */
554 # define ADV(N, P)      .byte 3; .2byte L(N)-L(P)
555 #else
556 # define ADV(N, P)      .byte 2, L(N)-L(P)
557 #endif
558
559         .balign 8
560 L(CIE):
561         .set    L(set0),L(ECIE)-L(SCIE)
562         .long   L(set0)                 /* CIE Length */
563 L(SCIE):
564         .long   0                       /* CIE Identifier Tag */
565         .byte   1                       /* CIE Version */
566         .ascii  "zR\0"                  /* CIE Augmentation */
567         .byte   1                       /* CIE Code Alignment Factor */
568         .byte   0x78                    /* CIE Data Alignment Factor */
569         .byte   0x10                    /* CIE RA Column */
570         .byte   1                       /* Augmentation size */
571         .byte   0x1b                    /* FDE Encoding (pcrel sdata4) */
572         .byte   0xc, 7, 8               /* DW_CFA_def_cfa, %rsp offset 8 */
573         .byte   0x80+16, 1              /* DW_CFA_offset, %rip offset 1*-8 */
574         .balign 8
575 L(ECIE):
576
577         .set    L(set1),L(EFDE1)-L(SFDE1)
578         .long   L(set1)                 /* FDE Length */
579 L(SFDE1):
580         .long   L(SFDE1)-L(CIE)         /* FDE CIE offset */
581         .long   PCREL(L(UW0))           /* Initial location */
582         .long   L(UW4)-L(UW0)           /* Address range */
583         .byte   0                       /* Augmentation size */
584         ADV(UW1, UW0)
585         .byte   0xc, 6, 32              /* DW_CFA_def_cfa, %rbp 32 */
586         .byte   0x80+6, 2               /* DW_CFA_offset, %rbp 2*-8 */
587         ADV(UW2, UW1)
588         .byte   0xa                     /* DW_CFA_remember_state */
589         .byte   0xc, 7, 8               /* DW_CFA_def_cfa, %rsp 8 */
590         .byte   0xc0+6                  /* DW_CFA_restore, %rbp */
591         ADV(UW3, UW2)
592         .byte   0xb                     /* DW_CFA_restore_state */
593         .balign 8
594 L(EFDE1):
595
596         .set    L(set2),L(EFDE2)-L(SFDE2)
597         .long   L(set2)                 /* FDE Length */
598 L(SFDE2):
599         .long   L(SFDE2)-L(CIE)         /* FDE CIE offset */
600         .long   PCREL(L(UW5))           /* Initial location */
601         .long   L(UW7)-L(UW5)           /* Address range */
602         .byte   0                       /* Augmentation size */
603         ADV(UW6, UW5)
604         .byte   0xe                     /* DW_CFA_def_cfa_offset */
605         .byte   ffi_closure_FS + 8, 1   /* uleb128, assuming 128 <= FS < 255 */
606         .balign 8
607 L(EFDE2):
608
609         .set    L(set3),L(EFDE3)-L(SFDE3)
610         .long   L(set3)                 /* FDE Length */
611 L(SFDE3):
612         .long   L(SFDE3)-L(CIE)         /* FDE CIE offset */
613         .long   PCREL(L(UW8))           /* Initial location */
614         .long   L(UW11)-L(UW8)          /* Address range */
615         .byte   0                       /* Augmentation size */
616         ADV(UW9, UW8)
617         .byte   0xe                     /* DW_CFA_def_cfa_offset */
618         .byte   ffi_closure_FS + 8, 1   /* uleb128, assuming 128 <= FS < 255 */
619         ADV(UW10, UW9)
620         .byte   0xe, 8                  /* DW_CFA_def_cfa_offset 8 */
621 L(EFDE3):
622
623         .set    L(set4),L(EFDE4)-L(SFDE4)
624         .long   L(set4)                 /* FDE Length */
625 L(SFDE4):
626         .long   L(SFDE4)-L(CIE)         /* FDE CIE offset */
627         .long   PCREL(L(UW12))          /* Initial location */
628         .long   L(UW14)-L(UW12)         /* Address range */
629         .byte   0                       /* Augmentation size */
630         ADV(UW13, UW12)
631         .byte   0xe                     /* DW_CFA_def_cfa_offset */
632         .byte   ffi_closure_FS + 8, 1   /* uleb128, assuming 128 <= FS < 255 */
633         .balign 8
634 L(EFDE4):
635
636         .set    L(set5),L(EFDE5)-L(SFDE5)
637         .long   L(set5)                 /* FDE Length */
638 L(SFDE5):
639         .long   L(SFDE5)-L(CIE)         /* FDE CIE offset */
640         .long   PCREL(L(UW15))          /* Initial location */
641         .long   L(UW17)-L(UW15)         /* Address range */
642         .byte   0                       /* Augmentation size */
643         ADV(UW16, UW15)
644         .byte   0xe                     /* DW_CFA_def_cfa_offset */
645         .byte   ffi_closure_FS + 8, 1   /* uleb128, assuming 128 <= FS < 255 */
646         .balign 8
647 L(EFDE5):
648 #ifdef __APPLE__
649         .subsections_via_symbols
650         .section __LD,__compact_unwind,regular,debug
651
652         /* compact unwind for ffi_call_unix64 */
653         .quad    C(ffi_call_unix64)
654         .set     L1,L(UW4)-L(UW0)
655         .long    L1
656         .long    0x04000000 /* use dwarf unwind info */
657         .quad    0
658         .quad    0
659
660         /* compact unwind for ffi_closure_unix64_sse */
661         .quad    C(ffi_closure_unix64_sse)
662         .set     L2,L(UW7)-L(UW5)
663         .long    L2
664         .long    0x04000000 /* use dwarf unwind info */
665         .quad    0
666         .quad    0
667
668         /* compact unwind for ffi_closure_unix64 */
669         .quad    C(ffi_closure_unix64)
670         .set     L3,L(UW11)-L(UW8)
671         .long    L3
672         .long    0x04000000 /* use dwarf unwind info */
673         .quad    0
674         .quad    0
675
676         /* compact unwind for ffi_go_closure_unix64_sse */
677         .quad    C(ffi_go_closure_unix64_sse)
678         .set     L4,L(UW14)-L(UW12)
679         .long    L4
680         .long    0x04000000 /* use dwarf unwind info */
681         .quad    0
682         .quad    0
683
684         /* compact unwind for ffi_go_closure_unix64 */
685         .quad    C(ffi_go_closure_unix64)
686         .set     L5,L(UW17)-L(UW15)
687         .long    L5
688         .long    0x04000000 /* use dwarf unwind info */
689         .quad    0
690         .quad    0
691 #endif
692
693 #endif /* __x86_64__ */
694 #if defined __ELF__ && defined __linux__
695         .section        .note.GNU-stack,"",@progbits
696 #endif