github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libffi/src/x86/sysv.S (about)

     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 "internal.h"
    34  
    35  #define C2(X, Y)  X ## Y
    36  #define C1(X, Y)  C2(X, Y)
    37  #ifdef __USER_LABEL_PREFIX__
    38  # define C(X)     C1(__USER_LABEL_PREFIX__, X)
    39  #else
    40  # define C(X)     X
    41  #endif
    42  
    43  #ifdef X86_DARWIN
    44  # define L(X)     C1(L, X)
    45  #else
    46  # define L(X)     C1(.L, X)
    47  #endif
    48  
    49  #ifdef __ELF__
    50  # define ENDF(X)  .type	X,@function; .size X, . - X
    51  #else
    52  # define ENDF(X)
    53  #endif
    54  
    55  /* Handle win32 fastcall name mangling.  */
    56  #ifdef X86_WIN32
    57  # define ffi_call_i386		@ffi_call_i386@8
    58  # define ffi_closure_inner	@ffi_closure_inner@8
    59  #else
    60  # define ffi_call_i386		C(ffi_call_i386)
    61  # define ffi_closure_inner	C(ffi_closure_inner)
    62  #endif
    63  
    64  /* This macro allows the safe creation of jump tables without an
    65     actual table.  The entry points into the table are all 8 bytes.
    66     The use of ORG asserts that we're at the correct location.  */
    67  /* ??? The clang assembler doesn't handle .org with symbolic expressions.  */
    68  #if defined(__clang__) || defined(__APPLE__)
    69  # define E(BASE, X)	.balign 8
    70  #else
    71  # define E(BASE, X)	.balign 8; .org BASE + X * 8
    72  #endif
    73  
    74  	.text
    75  	.balign	16
    76  	.globl	ffi_call_i386
    77  	FFI_HIDDEN(ffi_call_i386)
    78  
    79  /* This is declared as
    80  
    81     void ffi_call_i386(struct call_frame *frame, char *argp)
    82          __attribute__((fastcall));
    83  
    84     Thus the arguments are present in
    85  
    86          ecx: frame
    87          edx: argp
    88  */
    89  
    90  ffi_call_i386:
    91  L(UW0):
    92  	# cfi_startproc
    93  #if !HAVE_FASTCALL
    94  	movl	4(%esp), %ecx
    95  	movl	8(%esp), %edx
    96  #endif
    97  	movl	(%esp), %eax		/* move the return address */
    98  	movl	%ebp, (%ecx)		/* store %ebp into local frame */
    99  	movl	%eax, 4(%ecx)		/* store retaddr into local frame */
   100  
   101  	/* New stack frame based off ebp.  This is a itty bit of unwind
   102  	   trickery in that the CFA *has* changed.  There is no easy way
   103  	   to describe it correctly on entry to the function.  Fortunately,
   104  	   it doesn't matter too much since at all points we can correctly
   105  	   unwind back to ffi_call.  Note that the location to which we
   106  	   moved the return address is (the new) CFA-4, so from the
   107  	   perspective of the unwind info, it hasn't moved.  */
   108  	movl	%ecx, %ebp
   109  L(UW1):
   110  	# cfi_def_cfa(%ebp, 8)
   111  	# cfi_rel_offset(%ebp, 0)
   112  
   113  	movl	%edx, %esp		/* set outgoing argument stack */
   114  	movl	20+R_EAX*4(%ebp), %eax	/* set register arguments */
   115  	movl	20+R_EDX*4(%ebp), %edx
   116  	movl	20+R_ECX*4(%ebp), %ecx
   117  
   118  	call	*8(%ebp)
   119  
   120  	movl	12(%ebp), %ecx		/* load return type code */
   121  	movl	%ebx, 8(%ebp)		/* preserve %ebx */
   122  L(UW2):
   123  	# cfi_rel_offset(%ebx, 8)
   124  
   125  	andl	$X86_RET_TYPE_MASK, %ecx
   126  #ifdef __PIC__
   127  	call	C(__x86.get_pc_thunk.bx)
   128  L(pc1):
   129  	leal	L(store_table)-L(pc1)(%ebx, %ecx, 8), %ebx
   130  #else
   131  	leal	L(store_table)(,%ecx, 8), %ebx
   132  #endif
   133  	movl	16(%ebp), %ecx		/* load result address */
   134  	jmp	*%ebx
   135  
   136  	.balign	8
   137  L(store_table):
   138  E(L(store_table), X86_RET_FLOAT)
   139  	fstps	(%ecx)
   140  	jmp	L(e1)
   141  E(L(store_table), X86_RET_DOUBLE)
   142  	fstpl	(%ecx)
   143  	jmp	L(e1)
   144  E(L(store_table), X86_RET_LDOUBLE)
   145  	fstpt	(%ecx)
   146  	jmp	L(e1)
   147  E(L(store_table), X86_RET_SINT8)
   148  	movsbl	%al, %eax
   149  	mov	%eax, (%ecx)
   150  	jmp	L(e1)
   151  E(L(store_table), X86_RET_SINT16)
   152  	movswl	%ax, %eax
   153  	mov	%eax, (%ecx)
   154  	jmp	L(e1)
   155  E(L(store_table), X86_RET_UINT8)
   156  	movzbl	%al, %eax
   157  	mov	%eax, (%ecx)
   158  	jmp	L(e1)
   159  E(L(store_table), X86_RET_UINT16)
   160  	movzwl	%ax, %eax
   161  	mov	%eax, (%ecx)
   162  	jmp	L(e1)
   163  E(L(store_table), X86_RET_INT64)
   164  	movl	%edx, 4(%ecx)
   165  	/* fallthru */
   166  E(L(store_table), X86_RET_INT32)
   167  	movl	%eax, (%ecx)
   168  	/* fallthru */
   169  E(L(store_table), X86_RET_VOID)
   170  L(e1):
   171  	movl	8(%ebp), %ebx
   172  	movl	%ebp, %esp
   173  	popl	%ebp
   174  L(UW3):
   175  	# cfi_remember_state
   176  	# cfi_def_cfa(%esp, 4)
   177  	# cfi_restore(%ebx)
   178  	# cfi_restore(%ebp)
   179  	ret
   180  L(UW4):
   181  	# cfi_restore_state
   182  
   183  E(L(store_table), X86_RET_STRUCTPOP)
   184  	jmp	L(e1)
   185  E(L(store_table), X86_RET_STRUCTARG)
   186  	jmp	L(e1)
   187  E(L(store_table), X86_RET_STRUCT_1B)
   188  	movb	%al, (%ecx)
   189  	jmp	L(e1)
   190  E(L(store_table), X86_RET_STRUCT_2B)
   191  	movw	%ax, (%ecx)
   192  	jmp	L(e1)
   193  
   194  	/* Fill out the table so that bad values are predictable.  */
   195  E(L(store_table), X86_RET_UNUSED14)
   196  	ud2
   197  E(L(store_table), X86_RET_UNUSED15)
   198  	ud2
   199  
   200  L(UW5):
   201  	# cfi_endproc
   202  ENDF(ffi_call_i386)
   203  
   204  /* The inner helper is declared as
   205  
   206     void ffi_closure_inner(struct closure_frame *frame, char *argp)
   207  	__attribute_((fastcall))
   208  
   209     Thus the arguments are placed in
   210  
   211  	ecx:	frame
   212  	edx:	argp
   213  */
   214  
   215  /* Macros to help setting up the closure_data structure.  */
   216  
   217  #if HAVE_FASTCALL
   218  # define closure_FS	(40 + 4)
   219  # define closure_CF	0
   220  #else
   221  # define closure_FS	(8 + 40 + 12)
   222  # define closure_CF	8
   223  #endif
   224  
   225  #define FFI_CLOSURE_SAVE_REGS		\
   226  	movl	%eax, closure_CF+16+R_EAX*4(%esp);	\
   227  	movl	%edx, closure_CF+16+R_EDX*4(%esp);	\
   228  	movl	%ecx, closure_CF+16+R_ECX*4(%esp)
   229  
   230  #define FFI_CLOSURE_COPY_TRAMP_DATA					\
   231  	movl	FFI_TRAMPOLINE_SIZE(%eax), %edx;	/* copy cif */	\
   232  	movl	FFI_TRAMPOLINE_SIZE+4(%eax), %ecx;	/* copy fun */	\
   233  	movl	FFI_TRAMPOLINE_SIZE+8(%eax), %eax;	/* copy user_data */ \
   234  	movl	%edx, closure_CF+28(%esp);				\
   235  	movl	%ecx, closure_CF+32(%esp);				\
   236  	movl	%eax, closure_CF+36(%esp)
   237  
   238  #if HAVE_FASTCALL
   239  # define FFI_CLOSURE_PREP_CALL						\
   240  	movl	%esp, %ecx;			/* load closure_data */	\
   241  	leal	closure_FS+4(%esp), %edx;	/* load incoming stack */
   242  #else
   243  # define FFI_CLOSURE_PREP_CALL						\
   244  	leal	closure_CF(%esp), %ecx;		/* load closure_data */	\
   245  	leal	closure_FS+4(%esp), %edx;	/* load incoming stack */ \
   246  	movl	%ecx, (%esp);						\
   247  	movl	%edx, 4(%esp)
   248  #endif
   249  
   250  #define FFI_CLOSURE_CALL_INNER(UWN) \
   251  	call	ffi_closure_inner
   252  
   253  #define FFI_CLOSURE_MASK_AND_JUMP(N, UW)				\
   254  	andl	$X86_RET_TYPE_MASK, %eax;				\
   255  	leal	L(C1(load_table,N))(, %eax, 8), %edx;			\
   256  	movl	closure_CF(%esp), %eax;		/* optimiztic load */	\
   257  	jmp	*%edx
   258  
   259  #ifdef __PIC__
   260  # if defined X86_DARWIN || defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
   261  #  undef FFI_CLOSURE_MASK_AND_JUMP
   262  #  define FFI_CLOSURE_MASK_AND_JUMP(N, UW)				\
   263  	andl	$X86_RET_TYPE_MASK, %eax;				\
   264  	call	C(__x86.get_pc_thunk.dx);				\
   265  L(C1(pc,N)):								\
   266  	leal	L(C1(load_table,N))-L(C1(pc,N))(%edx, %eax, 8), %edx;	\
   267  	movl	closure_CF(%esp), %eax;		/* optimiztic load */	\
   268  	jmp	*%edx
   269  # else
   270  #  define FFI_CLOSURE_CALL_INNER_SAVE_EBX
   271  #  undef FFI_CLOSURE_CALL_INNER
   272  #  define FFI_CLOSURE_CALL_INNER(UWN)					\
   273  	movl	%ebx, 40(%esp);			/* save ebx */		\
   274  L(C1(UW,UWN)):								\
   275  	# cfi_rel_offset(%ebx, 40);					\
   276  	call	C(__x86.get_pc_thunk.bx);	/* load got register */	\
   277  	addl	$C(_GLOBAL_OFFSET_TABLE_), %ebx;			\
   278  	call	ffi_closure_inner@PLT
   279  #  undef FFI_CLOSURE_MASK_AND_JUMP
   280  #  define FFI_CLOSURE_MASK_AND_JUMP(N, UWN)				\
   281  	andl	$X86_RET_TYPE_MASK, %eax;				\
   282  	leal	L(C1(load_table,N))@GOTOFF(%ebx, %eax, 8), %edx;	\
   283  	movl	40(%esp), %ebx;			/* restore ebx */	\
   284  L(C1(UW,UWN)):								\
   285  	# cfi_restore(%ebx);						\
   286  	movl	closure_CF(%esp), %eax;		/* optimiztic load */	\
   287  	jmp	*%edx
   288  # endif /* DARWIN || HIDDEN */
   289  #endif /* __PIC__ */
   290  
   291  	.balign	16
   292  	.globl	C(ffi_go_closure_EAX)
   293  	FFI_HIDDEN(C(ffi_go_closure_EAX))
   294  C(ffi_go_closure_EAX):
   295  L(UW6):
   296  	# cfi_startproc
   297  	subl	$closure_FS, %esp
   298  L(UW7):
   299  	# cfi_def_cfa_offset(closure_FS + 4)
   300  	FFI_CLOSURE_SAVE_REGS
   301  	movl	4(%eax), %edx			/* copy cif */
   302  	movl	8(%eax), %ecx			/* copy fun */
   303  	movl	%edx, closure_CF+28(%esp)
   304  	movl	%ecx, closure_CF+32(%esp)
   305  	movl	%eax, closure_CF+36(%esp)	/* closure is user_data */
   306  	jmp	L(do_closure_i386)
   307  L(UW8):
   308  	# cfi_endproc
   309  ENDF(C(ffi_go_closure_EAX))
   310  
   311  	.balign	16
   312  	.globl	C(ffi_go_closure_ECX)
   313  	FFI_HIDDEN(C(ffi_go_closure_ECX))
   314  C(ffi_go_closure_ECX):
   315  L(UW9):
   316  	# cfi_startproc
   317  	subl	$closure_FS, %esp
   318  L(UW10):
   319  	# cfi_def_cfa_offset(closure_FS + 4)
   320  	FFI_CLOSURE_SAVE_REGS
   321  	movl	4(%ecx), %edx			/* copy cif */
   322  	movl	8(%ecx), %eax			/* copy fun */
   323  	movl	%edx, closure_CF+28(%esp)
   324  	movl	%eax, closure_CF+32(%esp)
   325  	movl	%ecx, closure_CF+36(%esp)	/* closure is user_data */
   326  	jmp	L(do_closure_i386)
   327  L(UW11):
   328  	# cfi_endproc
   329  ENDF(C(ffi_go_closure_ECX))
   330  
   331  /* The closure entry points are reached from the ffi_closure trampoline.
   332     On entry, %eax contains the address of the ffi_closure.  */
   333  
   334  	.balign	16
   335  	.globl	C(ffi_closure_i386)
   336  	FFI_HIDDEN(C(ffi_closure_i386))
   337  
   338  C(ffi_closure_i386):
   339  L(UW12):
   340  	# cfi_startproc
   341  	subl	$closure_FS, %esp
   342  L(UW13):
   343  	# cfi_def_cfa_offset(closure_FS + 4)
   344  
   345  	FFI_CLOSURE_SAVE_REGS
   346  	FFI_CLOSURE_COPY_TRAMP_DATA
   347  
   348  	/* Entry point from preceeding Go closures.  */
   349  L(do_closure_i386):
   350  
   351  	FFI_CLOSURE_PREP_CALL
   352  	FFI_CLOSURE_CALL_INNER(14)
   353  	FFI_CLOSURE_MASK_AND_JUMP(2, 15)
   354  
   355  	.balign	8
   356  L(load_table2):
   357  E(L(load_table2), X86_RET_FLOAT)
   358  	flds	closure_CF(%esp)
   359  	jmp	L(e2)
   360  E(L(load_table2), X86_RET_DOUBLE)
   361  	fldl	closure_CF(%esp)
   362  	jmp	L(e2)
   363  E(L(load_table2), X86_RET_LDOUBLE)
   364  	fldt	closure_CF(%esp)
   365  	jmp	L(e2)
   366  E(L(load_table2), X86_RET_SINT8)
   367  	movsbl	%al, %eax
   368  	jmp	L(e2)
   369  E(L(load_table2), X86_RET_SINT16)
   370  	movswl	%ax, %eax
   371  	jmp	L(e2)
   372  E(L(load_table2), X86_RET_UINT8)
   373  	movzbl	%al, %eax
   374  	jmp	L(e2)
   375  E(L(load_table2), X86_RET_UINT16)
   376  	movzwl	%ax, %eax
   377  	jmp	L(e2)
   378  E(L(load_table2), X86_RET_INT64)
   379  	movl	closure_CF+4(%esp), %edx
   380  	jmp	L(e2)
   381  E(L(load_table2), X86_RET_INT32)
   382  	nop
   383  	/* fallthru */
   384  E(L(load_table2), X86_RET_VOID)
   385  L(e2):
   386  	addl	$closure_FS, %esp
   387  L(UW16):
   388  	# cfi_adjust_cfa_offset(-closure_FS)
   389  	ret
   390  L(UW17):
   391  	# cfi_adjust_cfa_offset(closure_FS)
   392  E(L(load_table2), X86_RET_STRUCTPOP)
   393  	addl	$closure_FS, %esp
   394  L(UW18):
   395  	# cfi_adjust_cfa_offset(-closure_FS)
   396  	ret	$4
   397  L(UW19):
   398  	# cfi_adjust_cfa_offset(closure_FS)
   399  E(L(load_table2), X86_RET_STRUCTARG)
   400  	jmp	L(e2)
   401  E(L(load_table2), X86_RET_STRUCT_1B)
   402  	movzbl	%al, %eax
   403  	jmp	L(e2)
   404  E(L(load_table2), X86_RET_STRUCT_2B)
   405  	movzwl	%ax, %eax
   406  	jmp	L(e2)
   407  
   408  	/* Fill out the table so that bad values are predictable.  */
   409  E(L(load_table2), X86_RET_UNUSED14)
   410  	ud2
   411  E(L(load_table2), X86_RET_UNUSED15)
   412  	ud2
   413  
   414  L(UW20):
   415  	# cfi_endproc
   416  ENDF(C(ffi_closure_i386))
   417  
   418  	.balign	16
   419  	.globl	C(ffi_go_closure_STDCALL)
   420  	FFI_HIDDEN(C(ffi_go_closure_STDCALL))
   421  C(ffi_go_closure_STDCALL):
   422  L(UW21):
   423  	# cfi_startproc
   424  	subl	$closure_FS, %esp
   425  L(UW22):
   426  	# cfi_def_cfa_offset(closure_FS + 4)
   427  	FFI_CLOSURE_SAVE_REGS
   428  	movl	4(%ecx), %edx			/* copy cif */
   429  	movl	8(%ecx), %eax			/* copy fun */
   430  	movl	%edx, closure_CF+28(%esp)
   431  	movl	%eax, closure_CF+32(%esp)
   432  	movl	%ecx, closure_CF+36(%esp)	/* closure is user_data */
   433  	jmp	L(do_closure_STDCALL)
   434  L(UW23):
   435  	# cfi_endproc
   436  ENDF(C(ffi_go_closure_STDCALL))
   437  
   438  /* For REGISTER, we have no available parameter registers, and so we
   439     enter here having pushed the closure onto the stack.  */
   440  
   441  	.balign	16
   442  	.globl	C(ffi_closure_REGISTER)
   443  	FFI_HIDDEN(C(ffi_closure_REGISTER))
   444  C(ffi_closure_REGISTER):
   445  L(UW24):
   446  	# cfi_startproc
   447  	# cfi_def_cfa(%esp, 8)
   448  	# cfi_offset(%eip, -8)
   449  	subl	$closure_FS-4, %esp
   450  L(UW25):
   451  	# cfi_def_cfa_offset(closure_FS + 4)
   452  	FFI_CLOSURE_SAVE_REGS
   453  	movl	closure_FS-4(%esp), %ecx	/* load retaddr */
   454  	movl	closure_FS(%esp), %eax		/* load closure */
   455  	movl	%ecx, closure_FS(%esp)		/* move retaddr */
   456  	jmp	L(do_closure_REGISTER)
   457  L(UW26):
   458  	# cfi_endproc
   459  ENDF(C(ffi_closure_REGISTER))
   460  
   461  /* For STDCALL (and others), we need to pop N bytes of arguments off
   462     the stack following the closure.  The amount needing to be popped
   463     is returned to us from ffi_closure_inner.  */
   464  
   465  	.balign	16
   466  	.globl	C(ffi_closure_STDCALL)
   467  	FFI_HIDDEN(C(ffi_closure_STDCALL))
   468  C(ffi_closure_STDCALL):
   469  L(UW27):
   470  	# cfi_startproc
   471  	subl	$closure_FS, %esp
   472  L(UW28):
   473  	# cfi_def_cfa_offset(closure_FS + 4)
   474  
   475  	FFI_CLOSURE_SAVE_REGS
   476  
   477  	/* Entry point from ffi_closure_REGISTER.  */
   478  L(do_closure_REGISTER):
   479  
   480  	FFI_CLOSURE_COPY_TRAMP_DATA
   481  
   482  	/* Entry point from preceeding Go closure.  */
   483  L(do_closure_STDCALL):
   484  
   485  	FFI_CLOSURE_PREP_CALL
   486  	FFI_CLOSURE_CALL_INNER(29)
   487  
   488  	movl	%eax, %ecx
   489  	shrl	$X86_RET_POP_SHIFT, %ecx	/* isolate pop count */
   490  	leal	closure_FS(%esp, %ecx), %ecx	/* compute popped esp */
   491  	movl	closure_FS(%esp), %edx		/* move return address */
   492  	movl	%edx, (%ecx)
   493  
   494  	/* From this point on, the value of %esp upon return is %ecx+4,
   495  	   and we've copied the return address to %ecx to make return easy.
   496  	   There's no point in representing this in the unwind info, as
   497  	   there is always a window between the mov and the ret which
   498  	   will be wrong from one point of view or another.  */
   499  
   500  	FFI_CLOSURE_MASK_AND_JUMP(3, 30)
   501  
   502  	.balign	8
   503  L(load_table3):
   504  E(L(load_table3), X86_RET_FLOAT)
   505  	flds    closure_CF(%esp)
   506  	movl    %ecx, %esp
   507  	ret
   508  E(L(load_table3), X86_RET_DOUBLE)
   509  	fldl    closure_CF(%esp)
   510  	movl    %ecx, %esp
   511  	ret
   512  E(L(load_table3), X86_RET_LDOUBLE)
   513  	fldt    closure_CF(%esp)
   514  	movl    %ecx, %esp
   515  	ret
   516  E(L(load_table3), X86_RET_SINT8)
   517  	movsbl  %al, %eax
   518  	movl    %ecx, %esp
   519  	ret
   520  E(L(load_table3), X86_RET_SINT16)
   521  	movswl  %ax, %eax
   522  	movl    %ecx, %esp
   523  	ret
   524  E(L(load_table3), X86_RET_UINT8)
   525  	movzbl  %al, %eax
   526  	movl    %ecx, %esp
   527  	ret
   528  E(L(load_table3), X86_RET_UINT16)
   529  	movzwl  %ax, %eax
   530  	movl    %ecx, %esp
   531  	ret
   532  E(L(load_table3), X86_RET_INT64)
   533  	movl	closure_CF+4(%esp), %edx
   534  	movl    %ecx, %esp
   535  	ret
   536  E(L(load_table3), X86_RET_INT32)
   537  	movl    %ecx, %esp
   538  	ret
   539  E(L(load_table3), X86_RET_VOID)
   540  	movl    %ecx, %esp
   541  	ret
   542  E(L(load_table3), X86_RET_STRUCTPOP)
   543  	movl    %ecx, %esp
   544  	ret
   545  E(L(load_table3), X86_RET_STRUCTARG)
   546  	movl	%ecx, %esp
   547  	ret
   548  E(L(load_table3), X86_RET_STRUCT_1B)
   549  	movzbl	%al, %eax
   550  	movl	%ecx, %esp
   551  	ret
   552  E(L(load_table3), X86_RET_STRUCT_2B)
   553  	movzwl	%ax, %eax
   554  	movl	%ecx, %esp
   555  	ret
   556  
   557  	/* Fill out the table so that bad values are predictable.  */
   558  E(L(load_table3), X86_RET_UNUSED14)
   559  	ud2
   560  E(L(load_table3), X86_RET_UNUSED15)
   561  	ud2
   562  
   563  L(UW31):
   564  	# cfi_endproc
   565  ENDF(C(ffi_closure_STDCALL))
   566  
   567  #if !FFI_NO_RAW_API
   568  
   569  #define raw_closure_S_FS	(16+16+12)
   570  
   571  	.balign	16
   572  	.globl	C(ffi_closure_raw_SYSV)
   573  	FFI_HIDDEN(C(ffi_closure_raw_SYSV))
   574  C(ffi_closure_raw_SYSV):
   575  L(UW32):
   576  	# cfi_startproc
   577  	subl	$raw_closure_S_FS, %esp
   578  L(UW33):
   579  	# cfi_def_cfa_offset(raw_closure_S_FS + 4)
   580  	movl	%ebx, raw_closure_S_FS-4(%esp)
   581  L(UW34):
   582  	# cfi_rel_offset(%ebx, raw_closure_S_FS-4)
   583  
   584  	movl	FFI_TRAMPOLINE_SIZE+8(%eax), %edx	/* load cl->user_data */
   585  	movl	%edx, 12(%esp)
   586  	leal	raw_closure_S_FS+4(%esp), %edx		/* load raw_args */
   587  	movl	%edx, 8(%esp)
   588  	leal	16(%esp), %edx				/* load &res */
   589  	movl	%edx, 4(%esp)
   590  	movl	FFI_TRAMPOLINE_SIZE(%eax), %ebx		/* load cl->cif */
   591  	movl	%ebx, (%esp)
   592  	call	*FFI_TRAMPOLINE_SIZE+4(%eax)		/* call cl->fun */
   593  
   594  	movl	20(%ebx), %eax				/* load cif->flags */
   595  	andl	$X86_RET_TYPE_MASK, %eax
   596  #ifdef __PIC__
   597  	call	C(__x86.get_pc_thunk.bx)
   598  L(pc4):
   599  	leal	L(load_table4)-L(pc4)(%ebx, %eax, 8), %ecx
   600  #else
   601  	leal	L(load_table4)(,%eax, 8), %ecx
   602  #endif
   603  	movl	raw_closure_S_FS-4(%esp), %ebx
   604  L(UW35):
   605  	# cfi_restore(%ebx)
   606  	movl	16(%esp), %eax				/* Optimistic load */
   607  	jmp	*%ecx
   608  
   609  	.balign	8
   610  L(load_table4):
   611  E(L(load_table4), X86_RET_FLOAT)
   612  	flds	16(%esp)
   613  	jmp	L(e4)
   614  E(L(load_table4), X86_RET_DOUBLE)
   615  	fldl	16(%esp)
   616  	jmp	L(e4)
   617  E(L(load_table4), X86_RET_LDOUBLE)
   618  	fldt	16(%esp)
   619  	jmp	L(e4)
   620  E(L(load_table4), X86_RET_SINT8)
   621  	movsbl	%al, %eax
   622  	jmp	L(e4)
   623  E(L(load_table4), X86_RET_SINT16)
   624  	movswl	%ax, %eax
   625  	jmp	L(e4)
   626  E(L(load_table4), X86_RET_UINT8)
   627  	movzbl	%al, %eax
   628  	jmp	L(e4)
   629  E(L(load_table4), X86_RET_UINT16)
   630  	movzwl	%ax, %eax
   631  	jmp	L(e4)
   632  E(L(load_table4), X86_RET_INT64)
   633  	movl	16+4(%esp), %edx
   634  	jmp	L(e4)
   635  E(L(load_table4), X86_RET_INT32)
   636  	nop
   637  	/* fallthru */
   638  E(L(load_table4), X86_RET_VOID)
   639  L(e4):
   640  	addl	$raw_closure_S_FS, %esp
   641  L(UW36):
   642  	# cfi_adjust_cfa_offset(-raw_closure_S_FS)
   643  	ret
   644  L(UW37):
   645  	# cfi_adjust_cfa_offset(raw_closure_S_FS)
   646  E(L(load_table4), X86_RET_STRUCTPOP)
   647  	addl	$raw_closure_S_FS, %esp
   648  L(UW38):
   649  	# cfi_adjust_cfa_offset(-raw_closure_S_FS)
   650  	ret	$4
   651  L(UW39):
   652  	# cfi_adjust_cfa_offset(raw_closure_S_FS)
   653  E(L(load_table4), X86_RET_STRUCTARG)
   654  	jmp	L(e4)
   655  E(L(load_table4), X86_RET_STRUCT_1B)
   656  	movzbl	%al, %eax
   657  	jmp	L(e4)
   658  E(L(load_table4), X86_RET_STRUCT_2B)
   659  	movzwl	%ax, %eax
   660  	jmp	L(e4)
   661  
   662  	/* Fill out the table so that bad values are predictable.  */
   663  E(L(load_table4), X86_RET_UNUSED14)
   664  	ud2
   665  E(L(load_table4), X86_RET_UNUSED15)
   666  	ud2
   667  
   668  L(UW40):
   669  	# cfi_endproc
   670  ENDF(C(ffi_closure_raw_SYSV))
   671  
   672  #define raw_closure_T_FS	(16+16+8)
   673  
   674  	.balign	16
   675  	.globl	C(ffi_closure_raw_THISCALL)
   676  	FFI_HIDDEN(C(ffi_closure_raw_THISCALL))
   677  C(ffi_closure_raw_THISCALL):
   678  L(UW41):
   679  	# cfi_startproc
   680  	/* Rearrange the stack such that %ecx is the first argument.
   681  	   This means moving the return address.  */
   682  	popl	%edx
   683  L(UW42):
   684  	# cfi_def_cfa_offset(0)
   685  	# cfi_register(%eip, %edx)
   686  	pushl	%ecx
   687  L(UW43):
   688  	# cfi_adjust_cfa_offset(4)
   689  	pushl	%edx
   690  L(UW44):
   691  	# cfi_adjust_cfa_offset(4)
   692  	# cfi_rel_offset(%eip, 0)
   693  	subl	$raw_closure_T_FS, %esp
   694  L(UW45):
   695  	# cfi_adjust_cfa_offset(raw_closure_T_FS)
   696  	movl	%ebx, raw_closure_T_FS-4(%esp)
   697  L(UW46):
   698  	# cfi_rel_offset(%ebx, raw_closure_T_FS-4)
   699  
   700  	movl	FFI_TRAMPOLINE_SIZE+8(%eax), %edx	/* load cl->user_data */
   701  	movl	%edx, 12(%esp)
   702  	leal	raw_closure_T_FS+4(%esp), %edx		/* load raw_args */
   703  	movl	%edx, 8(%esp)
   704  	leal	16(%esp), %edx				/* load &res */
   705  	movl	%edx, 4(%esp)
   706  	movl	FFI_TRAMPOLINE_SIZE(%eax), %ebx		/* load cl->cif */
   707  	movl	%ebx, (%esp)
   708  	call	*FFI_TRAMPOLINE_SIZE+4(%eax)		/* call cl->fun */
   709  
   710  	movl	20(%ebx), %eax				/* load cif->flags */
   711  	andl	$X86_RET_TYPE_MASK, %eax
   712  #ifdef __PIC__
   713  	call	C(__x86.get_pc_thunk.bx)
   714  L(pc5):
   715  	leal	L(load_table5)-L(pc5)(%ebx, %eax, 8), %ecx
   716  #else
   717  	leal	L(load_table5)(,%eax, 8), %ecx
   718  #endif
   719  	movl	raw_closure_T_FS-4(%esp), %ebx
   720  L(UW47):
   721  	# cfi_restore(%ebx)
   722  	movl	16(%esp), %eax				/* Optimistic load */
   723  	jmp	*%ecx
   724  
   725  	.balign	8
   726  L(load_table5):
   727  E(L(load_table5), X86_RET_FLOAT)
   728  	flds	16(%esp)
   729  	jmp	L(e5)
   730  E(L(load_table5), X86_RET_DOUBLE)
   731  	fldl	16(%esp)
   732  	jmp	L(e5)
   733  E(L(load_table5), X86_RET_LDOUBLE)
   734  	fldt	16(%esp)
   735  	jmp	L(e5)
   736  E(L(load_table5), X86_RET_SINT8)
   737  	movsbl	%al, %eax
   738  	jmp	L(e5)
   739  E(L(load_table5), X86_RET_SINT16)
   740  	movswl	%ax, %eax
   741  	jmp	L(e5)
   742  E(L(load_table5), X86_RET_UINT8)
   743  	movzbl	%al, %eax
   744  	jmp	L(e5)
   745  E(L(load_table5), X86_RET_UINT16)
   746  	movzwl	%ax, %eax
   747  	jmp	L(e5)
   748  E(L(load_table5), X86_RET_INT64)
   749  	movl	16+4(%esp), %edx
   750  	jmp	L(e5)
   751  E(L(load_table5), X86_RET_INT32)
   752  	nop
   753  	/* fallthru */
   754  E(L(load_table5), X86_RET_VOID)
   755  L(e5):
   756  	addl	$raw_closure_T_FS, %esp
   757  L(UW48):
   758  	# cfi_adjust_cfa_offset(-raw_closure_T_FS)
   759  	/* Remove the extra %ecx argument we pushed.  */
   760  	ret	$4
   761  L(UW49):
   762  	# cfi_adjust_cfa_offset(raw_closure_T_FS)
   763  E(L(load_table5), X86_RET_STRUCTPOP)
   764  	addl	$raw_closure_T_FS, %esp
   765  L(UW50):
   766  	# cfi_adjust_cfa_offset(-raw_closure_T_FS)
   767  	ret	$8
   768  L(UW51):
   769  	# cfi_adjust_cfa_offset(raw_closure_T_FS)
   770  E(L(load_table5), X86_RET_STRUCTARG)
   771  	jmp	L(e5)
   772  E(L(load_table5), X86_RET_STRUCT_1B)
   773  	movzbl	%al, %eax
   774  	jmp	L(e5)
   775  E(L(load_table5), X86_RET_STRUCT_2B)
   776  	movzwl	%ax, %eax
   777  	jmp	L(e5)
   778  
   779  	/* Fill out the table so that bad values are predictable.  */
   780  E(L(load_table5), X86_RET_UNUSED14)
   781  	ud2
   782  E(L(load_table5), X86_RET_UNUSED15)
   783  	ud2
   784  
   785  L(UW52):
   786  	# cfi_endproc
   787  ENDF(C(ffi_closure_raw_THISCALL))
   788  
   789  #endif /* !FFI_NO_RAW_API */
   790  
   791  #ifdef X86_DARWIN
   792  # define COMDAT(X)							\
   793          .section __TEXT,__textcoal_nt,coalesced,pure_instructions;	\
   794          .weak_definition X;						\
   795          .private_extern X
   796  #elif defined __ELF__
   797  # define COMDAT(X)							\
   798  	.section .text.X,"axG",@progbits,X,comdat;			\
   799  	.globl	X;							\
   800  	FFI_HIDDEN(X)
   801  #else
   802  # define COMDAT(X)
   803  #endif
   804  
   805  #if defined(__PIC__)
   806  	COMDAT(C(__x86.get_pc_thunk.bx))
   807  C(__x86.get_pc_thunk.bx):
   808  	movl	(%esp), %ebx
   809  	ret
   810  ENDF(C(__x86.get_pc_thunk.bx))
   811  # if defined X86_DARWIN || defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
   812  	COMDAT(C(__x86.get_pc_thunk.dx))
   813  C(__x86.get_pc_thunk.dx):
   814  	movl	(%esp), %edx
   815  	ret
   816  ENDF(C(__x86.get_pc_thunk.dx))
   817  #endif /* DARWIN || HIDDEN */
   818  #endif /* __PIC__ */
   819  
   820  /* Sadly, OSX cctools-as doesn't understand .cfi directives at all.  */
   821  
   822  #ifdef __APPLE__
   823  .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
   824  EHFrame0:
   825  #elif defined(HAVE_AS_X86_64_UNWIND_SECTION_TYPE)
   826  .section .eh_frame,"a",@unwind
   827  #else
   828  .section .eh_frame,"a",@progbits
   829  #endif
   830  
   831  #ifdef HAVE_AS_X86_PCREL
   832  # define PCREL(X)	X - .
   833  #else
   834  # define PCREL(X)	X@rel
   835  #endif
   836  
   837  /* Simplify advancing between labels.  Assume DW_CFA_advance_loc1 fits.  */
   838  #define ADV(N, P)	.byte 2, L(N)-L(P)
   839  
   840  	.balign 4
   841  L(CIE):
   842  	.set	L(set0),L(ECIE)-L(SCIE)
   843  	.long	L(set0)			/* CIE Length */
   844  L(SCIE):
   845  	.long	0			/* CIE Identifier Tag */
   846  	.byte	1			/* CIE Version */
   847  	.ascii	"zR\0"			/* CIE Augmentation */
   848  	.byte	1			/* CIE Code Alignment Factor */
   849  	.byte	0x7c			/* CIE Data Alignment Factor */
   850  	.byte	0x8			/* CIE RA Column */
   851  	.byte	1			/* Augmentation size */
   852  	.byte	0x1b			/* FDE Encoding (pcrel sdata4) */
   853  	.byte	0xc, 4, 4		/* DW_CFA_def_cfa, %esp offset 4 */
   854  	.byte	0x80+8, 1		/* DW_CFA_offset, %eip offset 1*-4 */
   855  	.balign 4
   856  L(ECIE):
   857  
   858  	.set	L(set1),L(EFDE1)-L(SFDE1)
   859  	.long	L(set1)			/* FDE Length */
   860  L(SFDE1):
   861  	.long	L(SFDE1)-L(CIE)		/* FDE CIE offset */
   862  	.long	PCREL(L(UW0))		/* Initial location */
   863  	.long	L(UW5)-L(UW0)		/* Address range */
   864  	.byte	0			/* Augmentation size */
   865  	ADV(UW1, UW0)
   866  	.byte	0xc, 5, 8		/* DW_CFA_def_cfa, %ebp 8 */
   867  	.byte	0x80+5, 2		/* DW_CFA_offset, %ebp 2*-4 */
   868  	ADV(UW2, UW1)
   869  	.byte	0x80+3, 0		/* DW_CFA_offset, %ebx 0*-4 */
   870  	ADV(UW3, UW2)
   871  	.byte	0xa			/* DW_CFA_remember_state */
   872  	.byte	0xc, 4, 4		/* DW_CFA_def_cfa, %esp 4 */
   873  	.byte	0xc0+3			/* DW_CFA_restore, %ebx */
   874  	.byte	0xc0+5			/* DW_CFA_restore, %ebp */
   875  	ADV(UW4, UW3)
   876  	.byte	0xb			/* DW_CFA_restore_state */
   877  	.balign	4
   878  L(EFDE1):
   879  
   880  	.set	L(set2),L(EFDE2)-L(SFDE2)
   881  	.long	L(set2)			/* FDE Length */
   882  L(SFDE2):
   883  	.long	L(SFDE2)-L(CIE)		/* FDE CIE offset */
   884  	.long	PCREL(L(UW6))		/* Initial location */
   885  	.long	L(UW8)-L(UW6)		/* Address range */
   886  	.byte	0			/* Augmentation size */
   887  	ADV(UW7, UW6)
   888  	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
   889  	.balign	4
   890  L(EFDE2):
   891  
   892  	.set	L(set3),L(EFDE3)-L(SFDE3)
   893  	.long	L(set3)			/* FDE Length */
   894  L(SFDE3):
   895  	.long	L(SFDE3)-L(CIE)		/* FDE CIE offset */
   896  	.long	PCREL(L(UW9))		/* Initial location */
   897  	.long	L(UW11)-L(UW9)		/* Address range */
   898  	.byte	0			/* Augmentation size */
   899  	ADV(UW10, UW9)
   900  	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
   901  	.balign	4
   902  L(EFDE3):
   903  
   904  	.set	L(set4),L(EFDE4)-L(SFDE4)
   905  	.long	L(set4)			/* FDE Length */
   906  L(SFDE4):
   907  	.long	L(SFDE4)-L(CIE)		/* FDE CIE offset */
   908  	.long	PCREL(L(UW12))		/* Initial location */
   909  	.long	L(UW20)-L(UW12)		/* Address range */
   910  	.byte	0			/* Augmentation size */
   911  	ADV(UW13, UW12)
   912  	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
   913  #ifdef FFI_CLOSURE_CALL_INNER_SAVE_EBX
   914  	ADV(UW14, UW13)
   915  	.byte	0x80+3, (40-(closure_FS+4))/-4  /* DW_CFA_offset %ebx */
   916  	ADV(UW15, UW14)
   917  	.byte	0xc0+3			/* DW_CFA_restore %ebx */
   918  	ADV(UW16, UW15)
   919  #else
   920  	ADV(UW16, UW13)
   921  #endif
   922  	.byte	0xe, 4			/* DW_CFA_def_cfa_offset */
   923  	ADV(UW17, UW16)
   924  	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
   925  	ADV(UW18, UW17)
   926  	.byte	0xe, 4			/* DW_CFA_def_cfa_offset */
   927  	ADV(UW19, UW18)
   928  	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
   929  	.balign	4
   930  L(EFDE4):
   931  
   932  	.set	L(set5),L(EFDE5)-L(SFDE5)
   933  	.long	L(set5)			/* FDE Length */
   934  L(SFDE5):
   935  	.long	L(SFDE5)-L(CIE)		/* FDE CIE offset */
   936  	.long	PCREL(L(UW21))		/* Initial location */
   937  	.long	L(UW23)-L(UW21)		/* Address range */
   938  	.byte	0			/* Augmentation size */
   939  	ADV(UW22, UW21)
   940  	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
   941  	.balign	4
   942  L(EFDE5):
   943  
   944  	.set	L(set6),L(EFDE6)-L(SFDE6)
   945  	.long	L(set6)			/* FDE Length */
   946  L(SFDE6):
   947  	.long	L(SFDE6)-L(CIE)		/* FDE CIE offset */
   948  	.long	PCREL(L(UW24))		/* Initial location */
   949  	.long	L(UW26)-L(UW24)		/* Address range */
   950  	.byte	0			/* Augmentation size */
   951  	.byte	0xe, 8			/* DW_CFA_def_cfa_offset */
   952  	.byte	0x80+8, 2		/* DW_CFA_offset %eip, 2*-4 */
   953  	ADV(UW25, UW24)
   954  	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
   955  	.balign	4
   956  L(EFDE6):
   957  
   958  	.set	L(set7),L(EFDE7)-L(SFDE7)
   959  	.long	L(set7)			/* FDE Length */
   960  L(SFDE7):
   961  	.long	L(SFDE7)-L(CIE)		/* FDE CIE offset */
   962  	.long	PCREL(L(UW27))		/* Initial location */
   963  	.long	L(UW31)-L(UW27)		/* Address range */
   964  	.byte	0			/* Augmentation size */
   965  	ADV(UW28, UW27)
   966  	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
   967  #ifdef FFI_CLOSURE_CALL_INNER_SAVE_EBX
   968  	ADV(UW29, UW28)
   969  	.byte	0x80+3, (40-(closure_FS+4))/-4  /* DW_CFA_offset %ebx */
   970  	ADV(UW30, UW29)
   971  	.byte	0xc0+3			/* DW_CFA_restore %ebx */
   972  #endif
   973  	.balign	4
   974  L(EFDE7):
   975  
   976  #if !FFI_NO_RAW_API
   977  	.set	L(set8),L(EFDE8)-L(SFDE8)
   978  	.long	L(set8)			/* FDE Length */
   979  L(SFDE8):
   980  	.long	L(SFDE8)-L(CIE)		/* FDE CIE offset */
   981  	.long	PCREL(L(UW32))		/* Initial location */
   982  	.long	L(UW40)-L(UW32)		/* Address range */
   983  	.byte	0			/* Augmentation size */
   984  	ADV(UW33, UW32)
   985  	.byte	0xe, raw_closure_S_FS+4	/* DW_CFA_def_cfa_offset */
   986  	ADV(UW34, UW33)
   987  	.byte	0x80+3, 2		/* DW_CFA_offset %ebx 2*-4 */
   988  	ADV(UW35, UW34)
   989  	.byte	0xc0+3			/* DW_CFA_restore %ebx */
   990  	ADV(UW36, UW35)
   991  	.byte	0xe, 4			/* DW_CFA_def_cfa_offset */
   992  	ADV(UW37, UW36)
   993  	.byte	0xe, raw_closure_S_FS+4	/* DW_CFA_def_cfa_offset */
   994  	ADV(UW38, UW37)
   995  	.byte	0xe, 4			/* DW_CFA_def_cfa_offset */
   996  	ADV(UW39, UW38)
   997  	.byte	0xe, raw_closure_S_FS+4	/* DW_CFA_def_cfa_offset */
   998  	.balign	4
   999  L(EFDE8):
  1000  
  1001  	.set	L(set9),L(EFDE9)-L(SFDE9)
  1002  	.long	L(set9)			/* FDE Length */
  1003  L(SFDE9):
  1004  	.long	L(SFDE9)-L(CIE)		/* FDE CIE offset */
  1005  	.long	PCREL(L(UW41))		/* Initial location */
  1006  	.long	L(UW52)-L(UW41)		/* Address range */
  1007  	.byte	0			/* Augmentation size */
  1008  	ADV(UW42, UW41)
  1009  	.byte	0xe, 0			/* DW_CFA_def_cfa_offset */
  1010  	.byte	0x9, 8, 2		/* DW_CFA_register %eip, %edx */
  1011  	ADV(UW43, UW42)
  1012  	.byte	0xe, 4			/* DW_CFA_def_cfa_offset */
  1013  	ADV(UW44, UW43)
  1014  	.byte	0xe, 8			/* DW_CFA_def_cfa_offset */
  1015  	.byte	0x80+8, 2		/* DW_CFA_offset %eip 2*-4 */
  1016  	ADV(UW45, UW44)
  1017  	.byte	0xe, raw_closure_T_FS+8	/* DW_CFA_def_cfa_offset */
  1018  	ADV(UW46, UW45)
  1019  	.byte	0x80+3, 3		/* DW_CFA_offset %ebx 3*-4 */
  1020  	ADV(UW47, UW46)
  1021  	.byte	0xc0+3			/* DW_CFA_restore %ebx */
  1022  	ADV(UW48, UW47)
  1023  	.byte	0xe, 8			/* DW_CFA_def_cfa_offset */
  1024  	ADV(UW49, UW48)
  1025  	.byte	0xe, raw_closure_T_FS+8	/* DW_CFA_def_cfa_offset */
  1026  	ADV(UW50, UW49)
  1027  	.byte	0xe, 8			/* DW_CFA_def_cfa_offset */
  1028  	ADV(UW51, UW50)
  1029  	.byte	0xe, raw_closure_T_FS+8	/* DW_CFA_def_cfa_offset */
  1030  	.balign	4
  1031  L(EFDE9):
  1032  #endif /* !FFI_NO_RAW_API */
  1033  
  1034  #endif /* ifndef __x86_64__ */
  1035  
  1036  #if defined __ELF__ && defined __linux__
  1037  	.section	.note.GNU-stack,"",@progbits
  1038  #endif