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

     1  /* -----------------------------------------------------------------------
     2     sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
     3  	    Copyright (c) 2008 Red Hat, Inc.
     4  
     5     PowerPC64 Assembly glue.
     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  #define LIBFFI_ASM
    28  #include <fficonfig.h>
    29  #include <ffi.h>
    30  
    31  	.file	"linux64_closure.S"
    32  
    33  #ifdef POWERPC64
    34  	FFI_HIDDEN (ffi_closure_LINUX64)
    35  	.globl  ffi_closure_LINUX64
    36  	.text
    37  	.cfi_startproc
    38  # if _CALL_ELF == 2
    39  ffi_closure_LINUX64:
    40  	addis	%r2, %r12, .TOC.-ffi_closure_LINUX64@ha
    41  	addi	%r2, %r2, .TOC.-ffi_closure_LINUX64@l
    42  	.localentry ffi_closure_LINUX64, . - ffi_closure_LINUX64
    43  # else
    44  	.section        ".opd","aw"
    45  	.align  3
    46  ffi_closure_LINUX64:
    47  #  ifdef _CALL_LINUX
    48  	.quad   .L.ffi_closure_LINUX64,.TOC.@tocbase,0
    49  	.type   ffi_closure_LINUX64,@function
    50  	.text
    51  .L.ffi_closure_LINUX64:
    52  #  else
    53  	FFI_HIDDEN (.ffi_closure_LINUX64)
    54  	.globl  .ffi_closure_LINUX64
    55  	.quad   .ffi_closure_LINUX64,.TOC.@tocbase,0
    56  	.size   ffi_closure_LINUX64,24
    57  	.type   .ffi_closure_LINUX64,@function
    58  	.text
    59  .ffi_closure_LINUX64:
    60  #  endif
    61  # endif
    62  
    63  # if _CALL_ELF == 2
    64  #  32 byte special reg save area + 64 byte parm save area
    65  #  + 64 byte retval area + 13*8 fpr save area + round to 16
    66  #  define STACKFRAME 272
    67  #  define PARMSAVE 32
    68  #  define RETVAL PARMSAVE+64
    69  # else
    70  #  48 bytes special reg save area + 64 bytes parm save area
    71  #  + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
    72  #  define STACKFRAME 240
    73  #  define PARMSAVE 48
    74  #  define RETVAL PARMSAVE+64
    75  # endif
    76  
    77  # if _CALL_ELF == 2
    78  	ld	%r12, FFI_TRAMPOLINE_SIZE(%r11)		# closure->cif
    79  	mflr	%r0
    80  	lwz	%r12, 28(%r12)				# cif->flags
    81  	mtcrf	0x40, %r12
    82  	addi	%r12, %r1, PARMSAVE
    83  	bt	7, 0f
    84  	# Our caller has not allocated a parameter save area.
    85  	# We need to allocate one here and use it to pass gprs to
    86  	# ffi_closure_helper_LINUX64.
    87  	addi	%r12, %r1, -STACKFRAME+PARMSAVE
    88  0:
    89  	# Save general regs into parm save area
    90  	std	%r3, 0(%r12)
    91  	std	%r4, 8(%r12)
    92  	std	%r5, 16(%r12)
    93  	std	%r6, 24(%r12)
    94  	std	%r7, 32(%r12)
    95  	std	%r8, 40(%r12)
    96  	std	%r9, 48(%r12)
    97  	std	%r10, 56(%r12)
    98  
    99  	# load up the pointer to the parm save area
   100  	mr	%r7, %r12
   101  # else
   102  	# copy r2 to r11 and load TOC into r2
   103  	mr	%r11, %r2
   104  	ld	%r2, 16(%r2)
   105  
   106  	mflr	%r0
   107  	# Save general regs into parm save area
   108  	# This is the parameter save area set up by our caller.
   109  	std	%r3, PARMSAVE+0(%r1)
   110  	std	%r4, PARMSAVE+8(%r1)
   111  	std	%r5, PARMSAVE+16(%r1)
   112  	std	%r6, PARMSAVE+24(%r1)
   113  	std	%r7, PARMSAVE+32(%r1)
   114  	std	%r8, PARMSAVE+40(%r1)
   115  	std	%r9, PARMSAVE+48(%r1)
   116  	std	%r10, PARMSAVE+56(%r1)
   117  
   118  	# load up the pointer to the parm save area
   119  	addi	%r7, %r1, PARMSAVE
   120  # endif
   121  	std	%r0, 16(%r1)
   122  
   123  	# closure->cif
   124  	ld	%r3, FFI_TRAMPOLINE_SIZE(%r11)
   125  	# closure->fun
   126  	ld	%r4, FFI_TRAMPOLINE_SIZE+8(%r11)
   127  	# closure->user_data
   128  	ld	%r5, FFI_TRAMPOLINE_SIZE+16(%r11)
   129  
   130  .Ldoclosure:
   131  	# next save fpr 1 to fpr 13
   132  	stfd	%f1, -104+(0*8)(%r1)
   133  	stfd	%f2, -104+(1*8)(%r1)
   134  	stfd	%f3, -104+(2*8)(%r1)
   135  	stfd	%f4, -104+(3*8)(%r1)
   136  	stfd	%f5, -104+(4*8)(%r1)
   137  	stfd	%f6, -104+(5*8)(%r1)
   138  	stfd	%f7, -104+(6*8)(%r1)
   139  	stfd	%f8, -104+(7*8)(%r1)
   140  	stfd	%f9, -104+(8*8)(%r1)
   141  	stfd	%f10, -104+(9*8)(%r1)
   142  	stfd	%f11, -104+(10*8)(%r1)
   143  	stfd	%f12, -104+(11*8)(%r1)
   144  	stfd	%f13, -104+(12*8)(%r1)
   145  
   146  	# load up the pointer to the saved fpr registers */
   147  	addi	%r8, %r1, -104
   148  
   149  	# load up the pointer to the result storage
   150  	addi	%r6, %r1, -STACKFRAME+RETVAL
   151  
   152  	stdu	%r1, -STACKFRAME(%r1)
   153  	.cfi_def_cfa_offset STACKFRAME
   154  	.cfi_offset 65, 16
   155  
   156  	# make the call
   157  # if defined _CALL_LINUX || _CALL_ELF == 2
   158  	bl ffi_closure_helper_LINUX64
   159  # else
   160  	bl .ffi_closure_helper_LINUX64
   161  # endif
   162  .Lret:
   163  
   164  	# now r3 contains the return type
   165  	# so use it to look up in a table
   166  	# so we know how to deal with each type
   167  
   168  	# look up the proper starting point in table
   169  	# by using return type as offset
   170  	ld %r0, STACKFRAME+16(%r1)
   171  	cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT
   172  	bge .Lsmall
   173  	mflr %r4		# move address of .Lret to r4
   174  	sldi %r3, %r3, 4	# now multiply return type by 16
   175  	addi %r4, %r4, .Lret_type0 - .Lret
   176  	add %r3, %r3, %r4	# add contents of table to table address
   177  	mtctr %r3
   178  	bctr			# jump to it
   179  
   180  # Each of the ret_typeX code fragments has to be exactly 16 bytes long
   181  # (4 instructions). For cache effectiveness we align to a 16 byte boundary
   182  # first.
   183  	.align 4
   184  
   185  .Lret_type0:
   186  # case FFI_TYPE_VOID
   187  	mtlr %r0
   188  	addi %r1, %r1, STACKFRAME
   189  	.cfi_def_cfa_offset 0
   190  	blr
   191  	.cfi_def_cfa_offset STACKFRAME
   192  	nop
   193  # case FFI_TYPE_INT
   194  # ifdef __LITTLE_ENDIAN__
   195  	lwa %r3, RETVAL+0(%r1)
   196  # else
   197  	lwa %r3, RETVAL+4(%r1)
   198  # endif
   199  	mtlr %r0
   200  	addi %r1, %r1, STACKFRAME
   201  	.cfi_def_cfa_offset 0
   202  	blr
   203  	.cfi_def_cfa_offset STACKFRAME
   204  # case FFI_TYPE_FLOAT
   205  	lfs %f1, RETVAL+0(%r1)
   206  	mtlr %r0
   207  	addi %r1, %r1, STACKFRAME
   208  	.cfi_def_cfa_offset 0
   209  	blr
   210  	.cfi_def_cfa_offset STACKFRAME
   211  # case FFI_TYPE_DOUBLE
   212  	lfd %f1, RETVAL+0(%r1)
   213  	mtlr %r0
   214  	addi %r1, %r1, STACKFRAME
   215  	.cfi_def_cfa_offset 0
   216  	blr
   217  	.cfi_def_cfa_offset STACKFRAME
   218  # case FFI_TYPE_LONGDOUBLE
   219  	lfd %f1, RETVAL+0(%r1)
   220  	mtlr %r0
   221  	lfd %f2, RETVAL+8(%r1)
   222  	b .Lfinish
   223  # case FFI_TYPE_UINT8
   224  # ifdef __LITTLE_ENDIAN__
   225  	lbz %r3, RETVAL+0(%r1)
   226  # else
   227  	lbz %r3, RETVAL+7(%r1)
   228  # endif
   229  	mtlr %r0
   230  	addi %r1, %r1, STACKFRAME
   231  	.cfi_def_cfa_offset 0
   232  	blr
   233  	.cfi_def_cfa_offset STACKFRAME
   234  # case FFI_TYPE_SINT8
   235  # ifdef __LITTLE_ENDIAN__
   236  	lbz %r3, RETVAL+0(%r1)
   237  # else
   238  	lbz %r3, RETVAL+7(%r1)
   239  # endif
   240  	extsb %r3,%r3
   241  	mtlr %r0
   242  	b .Lfinish
   243  # case FFI_TYPE_UINT16
   244  # ifdef __LITTLE_ENDIAN__
   245  	lhz %r3, RETVAL+0(%r1)
   246  # else
   247  	lhz %r3, RETVAL+6(%r1)
   248  # endif
   249  	mtlr %r0
   250  .Lfinish:
   251  	addi %r1, %r1, STACKFRAME
   252  	.cfi_def_cfa_offset 0
   253  	blr
   254  	.cfi_def_cfa_offset STACKFRAME
   255  # case FFI_TYPE_SINT16
   256  # ifdef __LITTLE_ENDIAN__
   257  	lha %r3, RETVAL+0(%r1)
   258  # else
   259  	lha %r3, RETVAL+6(%r1)
   260  # endif
   261  	mtlr %r0
   262  	addi %r1, %r1, STACKFRAME
   263  	.cfi_def_cfa_offset 0
   264  	blr
   265  	.cfi_def_cfa_offset STACKFRAME
   266  # case FFI_TYPE_UINT32
   267  # ifdef __LITTLE_ENDIAN__
   268  	lwz %r3, RETVAL+0(%r1)
   269  # else
   270  	lwz %r3, RETVAL+4(%r1)
   271  # endif
   272  	mtlr %r0
   273  	addi %r1, %r1, STACKFRAME
   274  	.cfi_def_cfa_offset 0
   275  	blr
   276  	.cfi_def_cfa_offset STACKFRAME
   277  # case FFI_TYPE_SINT32
   278  # ifdef __LITTLE_ENDIAN__
   279  	lwa %r3, RETVAL+0(%r1)
   280  # else
   281  	lwa %r3, RETVAL+4(%r1)
   282  # endif
   283  	mtlr %r0
   284  	addi %r1, %r1, STACKFRAME
   285  	.cfi_def_cfa_offset 0
   286  	blr
   287  	.cfi_def_cfa_offset STACKFRAME
   288  # case FFI_TYPE_UINT64
   289  	ld %r3, RETVAL+0(%r1)
   290  	mtlr %r0
   291  	addi %r1, %r1, STACKFRAME
   292  	.cfi_def_cfa_offset 0
   293  	blr
   294  	.cfi_def_cfa_offset STACKFRAME
   295  # case FFI_TYPE_SINT64
   296  	ld %r3, RETVAL+0(%r1)
   297  	mtlr %r0
   298  	addi %r1, %r1, STACKFRAME
   299  	.cfi_def_cfa_offset 0
   300  	blr
   301  	.cfi_def_cfa_offset STACKFRAME
   302  # case FFI_TYPE_STRUCT
   303  	mtlr %r0
   304  	addi %r1, %r1, STACKFRAME
   305  	.cfi_def_cfa_offset 0
   306  	blr
   307  	.cfi_def_cfa_offset STACKFRAME
   308  	nop
   309  # case FFI_TYPE_POINTER
   310  	ld %r3, RETVAL+0(%r1)
   311  	mtlr %r0
   312  	addi %r1, %r1, STACKFRAME
   313  	.cfi_def_cfa_offset 0
   314  	blr
   315  	.cfi_def_cfa_offset STACKFRAME
   316  # case FFI_V2_TYPE_FLOAT_HOMOG
   317  	lfs %f1, RETVAL+0(%r1)
   318  	lfs %f2, RETVAL+4(%r1)
   319  	lfs %f3, RETVAL+8(%r1)
   320  	b .Lmorefloat
   321  # case FFI_V2_TYPE_DOUBLE_HOMOG
   322  	lfd %f1, RETVAL+0(%r1)
   323  	lfd %f2, RETVAL+8(%r1)
   324  	lfd %f3, RETVAL+16(%r1)
   325  	lfd %f4, RETVAL+24(%r1)
   326  	mtlr %r0
   327  	lfd %f5, RETVAL+32(%r1)
   328  	lfd %f6, RETVAL+40(%r1)
   329  	lfd %f7, RETVAL+48(%r1)
   330  	lfd %f8, RETVAL+56(%r1)
   331  	addi %r1, %r1, STACKFRAME
   332  	.cfi_def_cfa_offset 0
   333  	blr
   334  	.cfi_def_cfa_offset STACKFRAME
   335  .Lmorefloat:
   336  	lfs %f4, RETVAL+12(%r1)
   337  	mtlr %r0
   338  	lfs %f5, RETVAL+16(%r1)
   339  	lfs %f6, RETVAL+20(%r1)
   340  	lfs %f7, RETVAL+24(%r1)
   341  	lfs %f8, RETVAL+28(%r1)
   342  	addi %r1, %r1, STACKFRAME
   343  	.cfi_def_cfa_offset 0
   344  	blr
   345  	.cfi_def_cfa_offset STACKFRAME
   346  .Lsmall:
   347  # ifdef __LITTLE_ENDIAN__
   348  	ld %r3,RETVAL+0(%r1)
   349  	mtlr %r0
   350  	ld %r4,RETVAL+8(%r1)
   351  	addi %r1, %r1, STACKFRAME
   352  	.cfi_def_cfa_offset 0
   353  	blr
   354  # else
   355  	# A struct smaller than a dword is returned in the low bits of r3
   356  	# ie. right justified.  Larger structs are passed left justified
   357  	# in r3 and r4.  The return value area on the stack will have
   358  	# the structs as they are usually stored in memory.
   359  	cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT + 7 # size 8 bytes?
   360  	neg %r5, %r3
   361  	ld %r3,RETVAL+0(%r1)
   362  	blt .Lsmalldown
   363  	mtlr %r0
   364  	ld %r4,RETVAL+8(%r1)
   365  	addi %r1, %r1, STACKFRAME
   366  	.cfi_def_cfa_offset 0
   367  	blr
   368  	.cfi_def_cfa_offset STACKFRAME
   369  .Lsmalldown:
   370  	addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7
   371  	mtlr %r0
   372  	sldi %r5, %r5, 3
   373  	addi %r1, %r1, STACKFRAME
   374  	.cfi_def_cfa_offset 0
   375  	srd %r3, %r3, %r5
   376  	blr
   377  # endif
   378  
   379  	.cfi_endproc
   380  # if _CALL_ELF == 2
   381  	.size	ffi_closure_LINUX64,.-ffi_closure_LINUX64
   382  # else
   383  #  ifdef _CALL_LINUX
   384  	.size	ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64
   385  #  else
   386  	.long	0
   387  	.byte	0,12,0,1,128,0,0,0
   388  	.size	.ffi_closure_LINUX64,.-.ffi_closure_LINUX64
   389  #  endif
   390  # endif
   391  
   392  
   393  	FFI_HIDDEN (ffi_go_closure_linux64)
   394  	.globl  ffi_go_closure_linux64
   395  	.text
   396  	.cfi_startproc
   397  # if _CALL_ELF == 2
   398  ffi_go_closure_linux64:
   399  	addis	%r2, %r12, .TOC.-ffi_go_closure_linux64@ha
   400  	addi	%r2, %r2, .TOC.-ffi_go_closure_linux64@l
   401  	.localentry ffi_go_closure_linux64, . - ffi_go_closure_linux64
   402  # else
   403  	.section        ".opd","aw"
   404  	.align  3
   405  ffi_go_closure_linux64:
   406  #  ifdef _CALL_LINUX
   407  	.quad   .L.ffi_go_closure_linux64,.TOC.@tocbase,0
   408  	.type   ffi_go_closure_linux64,@function
   409  	.text
   410  .L.ffi_go_closure_linux64:
   411  #  else
   412  	FFI_HIDDEN (.ffi_go_closure_linux64)
   413  	.globl  .ffi_go_closure_linux64
   414  	.quad   .ffi_go_closure_linux64,.TOC.@tocbase,0
   415  	.size   ffi_go_closure_linux64,24
   416  	.type   .ffi_go_closure_linux64,@function
   417  	.text
   418  .ffi_go_closure_linux64:
   419  #  endif
   420  # endif
   421  
   422  # if _CALL_ELF == 2
   423  	ld	%r12, 8(%r11)				# closure->cif
   424  	mflr	%r0
   425  	lwz	%r12, 28(%r12)				# cif->flags
   426  	mtcrf	0x40, %r12
   427  	addi	%r12, %r1, PARMSAVE
   428  	bt	7, 0f
   429  	# Our caller has not allocated a parameter save area.
   430  	# We need to allocate one here and use it to pass gprs to
   431  	# ffi_closure_helper_LINUX64.
   432  	addi	%r12, %r1, -STACKFRAME+PARMSAVE
   433  0:
   434  	# Save general regs into parm save area
   435  	std	%r3, 0(%r12)
   436  	std	%r4, 8(%r12)
   437  	std	%r5, 16(%r12)
   438  	std	%r6, 24(%r12)
   439  	std	%r7, 32(%r12)
   440  	std	%r8, 40(%r12)
   441  	std	%r9, 48(%r12)
   442  	std	%r10, 56(%r12)
   443  
   444  	# load up the pointer to the parm save area
   445  	mr	%r7, %r12
   446  # else
   447  	mflr	%r0
   448  	# Save general regs into parm save area
   449  	# This is the parameter save area set up by our caller.
   450  	std	%r3, PARMSAVE+0(%r1)
   451  	std	%r4, PARMSAVE+8(%r1)
   452  	std	%r5, PARMSAVE+16(%r1)
   453  	std	%r6, PARMSAVE+24(%r1)
   454  	std	%r7, PARMSAVE+32(%r1)
   455  	std	%r8, PARMSAVE+40(%r1)
   456  	std	%r9, PARMSAVE+48(%r1)
   457  	std	%r10, PARMSAVE+56(%r1)
   458  
   459  	# load up the pointer to the parm save area
   460  	addi	%r7, %r1, PARMSAVE
   461  # endif
   462  	std	%r0, 16(%r1)
   463  
   464  	# closure->cif
   465  	ld	%r3, 8(%r11)
   466  	# closure->fun
   467  	ld	%r4, 16(%r11)
   468  	# user_data
   469  	mr	%r5, %r11
   470  	b	.Ldoclosure
   471  
   472  	.cfi_endproc
   473  # if _CALL_ELF == 2
   474  	.size	ffi_go_closure_linux64,.-ffi_go_closure_linux64
   475  # else
   476  #  ifdef _CALL_LINUX
   477  	.size	ffi_go_closure_linux64,.-.L.ffi_go_closure_linux64
   478  #  else
   479  	.long	0
   480  	.byte	0,12,0,1,128,0,0,0
   481  	.size	.ffi_go_closure_linux64,.-.ffi_go_closure_linux64
   482  #  endif
   483  # endif
   484  #endif
   485  
   486  #if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
   487  	.section	.note.GNU-stack,"",@progbits
   488  #endif