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

     1  /* -----------------------------------------------------------------------
     2     sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
     3  	    Copyright (c) 2008 Red Hat, Inc.
     4  
     5     PowerPC 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  #include <powerpc/asm.h>
    31  
    32  	.file   "ppc_closure.S"
    33  
    34  #ifndef POWERPC64
    35  
    36  FFI_HIDDEN(ffi_closure_SYSV)
    37  ENTRY(ffi_closure_SYSV)
    38  	.cfi_startproc
    39  	stwu %r1,-144(%r1)
    40  	.cfi_def_cfa_offset 144
    41  	mflr %r0
    42  	stw %r0,148(%r1)
    43  	.cfi_offset 65, 4
    44  
    45  # we want to build up an areas for the parameters passed
    46  # in registers (both floating point and integer)
    47  
    48  	# so first save gpr 3 to gpr 10 (aligned to 4)
    49  	stw   %r3, 16(%r1)
    50  	stw   %r4, 20(%r1)
    51  	stw   %r5, 24(%r1)
    52  
    53  	# set up registers for the routine that does the work
    54  
    55  	# closure->cif
    56  	lwz %r3,FFI_TRAMPOLINE_SIZE(%r11)
    57  	# closure->fun
    58  	lwz %r4,FFI_TRAMPOLINE_SIZE+4(%r11)
    59  	# closure->user_data
    60  	lwz %r5,FFI_TRAMPOLINE_SIZE+8(%r11)
    61  
    62  .Ldoclosure:
    63  	stw   %r6, 28(%r1)
    64  	stw   %r7, 32(%r1)
    65  	stw   %r8, 36(%r1)
    66  	stw   %r9, 40(%r1)
    67  	stw   %r10,44(%r1)
    68  
    69  #ifndef __NO_FPRS__
    70  	# next save fpr 1 to fpr 8 (aligned to 8)
    71  	stfd  %f1, 48(%r1)
    72  	stfd  %f2, 56(%r1)
    73  	stfd  %f3, 64(%r1)
    74  	stfd  %f4, 72(%r1)
    75  	stfd  %f5, 80(%r1)
    76  	stfd  %f6, 88(%r1)
    77  	stfd  %f7, 96(%r1)
    78  	stfd  %f8, 104(%r1)
    79  #endif
    80  
    81  	# pointer to the result storage
    82  	addi %r6,%r1,112
    83  
    84  	# pointer to the saved gpr registers
    85  	addi %r7,%r1,16
    86  
    87  	# pointer to the saved fpr registers
    88  	addi %r8,%r1,48
    89  
    90  	# pointer to the outgoing parameter save area in the previous frame
    91  	# i.e. the previous frame pointer + 8
    92  	addi %r9,%r1,152
    93  
    94  	# make the call
    95  	bl ffi_closure_helper_SYSV@local
    96  .Lret:
    97  	# now r3 contains the return type
    98  	# so use it to look up in a table
    99  	# so we know how to deal with each type
   100  
   101  	# look up the proper starting point in table
   102  	# by using return type as offset
   103  
   104  	mflr %r4		# move address of .Lret to r4
   105  	slwi %r3,%r3,4		# now multiply return type by 16
   106  	addi %r4, %r4, .Lret_type0 - .Lret
   107  	lwz %r0,148(%r1)
   108  	add %r3,%r3,%r4		# add contents of table to table address
   109  	mtctr %r3
   110  	bctr			# jump to it
   111  
   112  # Each of the ret_typeX code fragments has to be exactly 16 bytes long
   113  # (4 instructions). For cache effectiveness we align to a 16 byte boundary
   114  # first.
   115  	.align 4
   116  # case FFI_TYPE_VOID
   117  .Lret_type0:
   118  	mtlr %r0
   119  	addi %r1,%r1,144
   120  	.cfi_def_cfa_offset 0
   121  	blr
   122  	.cfi_def_cfa_offset 144
   123  	nop
   124  
   125  # case FFI_TYPE_INT
   126  	lwz %r3,112+0(%r1)
   127  	mtlr %r0
   128  .Lfinish:
   129  	addi %r1,%r1,144
   130  	.cfi_def_cfa_offset 0
   131  	blr
   132  	.cfi_def_cfa_offset 144
   133  
   134  # case FFI_TYPE_FLOAT
   135  #ifndef __NO_FPRS__
   136  	lfs %f1,112+0(%r1)
   137  #else
   138  	nop
   139  #endif
   140  	mtlr %r0
   141  	addi %r1,%r1,144
   142  	.cfi_def_cfa_offset 0
   143  	blr
   144  	.cfi_def_cfa_offset 144
   145  
   146  # case FFI_TYPE_DOUBLE
   147  #ifndef __NO_FPRS__
   148  	lfd %f1,112+0(%r1)
   149  #else
   150  	nop
   151  #endif
   152  	mtlr %r0
   153  	addi %r1,%r1,144
   154  	.cfi_def_cfa_offset 0
   155  	blr
   156  	.cfi_def_cfa_offset 144
   157  
   158  # case FFI_TYPE_LONGDOUBLE
   159  #ifndef __NO_FPRS__
   160  	lfd %f1,112+0(%r1)
   161  	lfd %f2,112+8(%r1)
   162  	mtlr %r0
   163  	b .Lfinish
   164  #else
   165  	mtlr %r0
   166  	addi %r1,%r1,144
   167  	.cfi_def_cfa_offset 0
   168  	blr
   169  	.cfi_def_cfa_offset 144
   170  	nop
   171  #endif
   172  
   173  # case FFI_TYPE_UINT8
   174  #ifdef __LITTLE_ENDIAN__
   175  	lbz %r3,112+0(%r1)
   176  #else
   177  	lbz %r3,112+3(%r1)
   178  #endif
   179  	mtlr %r0
   180  	addi %r1,%r1,144
   181  	.cfi_def_cfa_offset 0
   182  	blr
   183  	.cfi_def_cfa_offset 144
   184  
   185  # case FFI_TYPE_SINT8
   186  #ifdef __LITTLE_ENDIAN__
   187  	lbz %r3,112+0(%r1)
   188  #else
   189  	lbz %r3,112+3(%r1)
   190  #endif
   191  	extsb %r3,%r3
   192  	mtlr %r0
   193  	b .Lfinish
   194  
   195  # case FFI_TYPE_UINT16
   196  #ifdef __LITTLE_ENDIAN__
   197  	lhz %r3,112+0(%r1)
   198  #else
   199  	lhz %r3,112+2(%r1)
   200  #endif
   201  	mtlr %r0
   202  	addi %r1,%r1,144
   203  	.cfi_def_cfa_offset 0
   204  	blr
   205  	.cfi_def_cfa_offset 144
   206  
   207  # case FFI_TYPE_SINT16
   208  #ifdef __LITTLE_ENDIAN__
   209  	lha %r3,112+0(%r1)
   210  #else
   211  	lha %r3,112+2(%r1)
   212  #endif
   213  	mtlr %r0
   214  	addi %r1,%r1,144
   215  	.cfi_def_cfa_offset 0
   216  	blr
   217  	.cfi_def_cfa_offset 144
   218  
   219  # case FFI_TYPE_UINT32
   220  	lwz %r3,112+0(%r1)
   221  	mtlr %r0
   222  	addi %r1,%r1,144
   223  	.cfi_def_cfa_offset 0
   224  	blr
   225  	.cfi_def_cfa_offset 144
   226  
   227  # case FFI_TYPE_SINT32
   228  	lwz %r3,112+0(%r1)
   229  	mtlr %r0
   230  	addi %r1,%r1,144
   231  	.cfi_def_cfa_offset 0
   232  	blr
   233  	.cfi_def_cfa_offset 144
   234  
   235  # case FFI_TYPE_UINT64
   236  	lwz %r3,112+0(%r1)
   237  	lwz %r4,112+4(%r1)
   238  	mtlr %r0
   239  	b .Lfinish
   240  
   241  # case FFI_TYPE_SINT64
   242  	lwz %r3,112+0(%r1)
   243  	lwz %r4,112+4(%r1)
   244  	mtlr %r0
   245  	b .Lfinish
   246  
   247  # case FFI_TYPE_STRUCT
   248  	mtlr %r0
   249  	addi %r1,%r1,144
   250  	.cfi_def_cfa_offset 0
   251  	blr
   252  	.cfi_def_cfa_offset 144
   253  	nop
   254  
   255  # case FFI_TYPE_POINTER
   256  	lwz %r3,112+0(%r1)
   257  	mtlr %r0
   258  	addi %r1,%r1,144
   259  	.cfi_def_cfa_offset 0
   260  	blr
   261  	.cfi_def_cfa_offset 144
   262  
   263  # case FFI_TYPE_UINT128
   264  	lwz %r3,112+0(%r1)
   265  	lwz %r4,112+4(%r1)
   266  	lwz %r5,112+8(%r1)
   267  	b .Luint128
   268  
   269  # The return types below are only used when the ABI type is FFI_SYSV.
   270  # case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
   271  	lbz %r3,112+0(%r1)
   272  	mtlr %r0
   273  	addi %r1,%r1,144
   274  	.cfi_def_cfa_offset 0
   275  	blr
   276  	.cfi_def_cfa_offset 144
   277  
   278  # case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
   279  	lhz %r3,112+0(%r1)
   280  	mtlr %r0
   281  	addi %r1,%r1,144
   282  	.cfi_def_cfa_offset 0
   283  	blr
   284  	.cfi_def_cfa_offset 144
   285  
   286  # case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
   287  	lwz %r3,112+0(%r1)
   288  #ifdef __LITTLE_ENDIAN__
   289  	mtlr %r0
   290  	addi %r1,%r1,144
   291  	.cfi_def_cfa_offset 0
   292  	blr
   293  	.cfi_def_cfa_offset 144
   294  #else
   295  	srwi %r3,%r3,8
   296  	mtlr %r0
   297  	b .Lfinish
   298  #endif
   299  
   300  # case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
   301  	lwz %r3,112+0(%r1)
   302  	mtlr %r0
   303  	addi %r1,%r1,144
   304  	.cfi_def_cfa_offset 0
   305  	blr
   306  	.cfi_def_cfa_offset 144
   307  
   308  # case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
   309  	lwz %r3,112+0(%r1)
   310  	lwz %r4,112+4(%r1)
   311  #ifdef __LITTLE_ENDIAN__
   312  	mtlr %r0
   313  	b .Lfinish
   314  #else
   315  	li %r5,24
   316  	b .Lstruct567
   317  #endif
   318  
   319  # case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
   320  	lwz %r3,112+0(%r1)
   321  	lwz %r4,112+4(%r1)
   322  #ifdef __LITTLE_ENDIAN__
   323  	mtlr %r0
   324  	b .Lfinish
   325  #else
   326  	li %r5,16
   327  	b .Lstruct567
   328  #endif
   329  
   330  # case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
   331  	lwz %r3,112+0(%r1)
   332  	lwz %r4,112+4(%r1)
   333  #ifdef __LITTLE_ENDIAN__
   334  	mtlr %r0
   335  	b .Lfinish
   336  #else
   337  	li %r5,8
   338  	b .Lstruct567
   339  #endif
   340  
   341  # case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
   342  	lwz %r3,112+0(%r1)
   343  	lwz %r4,112+4(%r1)
   344  	mtlr %r0
   345  	b .Lfinish
   346  
   347  #ifndef __LITTLE_ENDIAN__
   348  .Lstruct567:
   349  	subfic %r6,%r5,32
   350  	srw %r4,%r4,%r5
   351  	slw %r6,%r3,%r6
   352  	srw %r3,%r3,%r5
   353  	or %r4,%r6,%r4
   354  	mtlr %r0
   355  	addi %r1,%r1,144
   356  	.cfi_def_cfa_offset 0
   357  	blr
   358  	.cfi_def_cfa_offset 144
   359  #endif
   360  
   361  .Luint128:
   362  	lwz %r6,112+12(%r1)
   363  	mtlr %r0
   364  	addi %r1,%r1,144
   365  	.cfi_def_cfa_offset 0
   366  	blr
   367  	.cfi_endproc
   368  END(ffi_closure_SYSV)
   369  
   370  
   371  FFI_HIDDEN(ffi_go_closure_sysv)
   372  ENTRY(ffi_go_closure_sysv)
   373  	.cfi_startproc
   374  	stwu %r1,-144(%r1)
   375  	.cfi_def_cfa_offset 144
   376  	mflr %r0
   377  	stw %r0,148(%r1)
   378  	.cfi_offset 65, 4
   379  
   380  	stw   %r3, 16(%r1)
   381  	stw   %r4, 20(%r1)
   382  	stw   %r5, 24(%r1)
   383  
   384  	# closure->cif
   385  	lwz %r3,4(%r11)
   386  	# closure->fun
   387  	lwz %r4,8(%r11)
   388  	# user_data
   389  	mr %r5,%r11
   390  	b .Ldoclosure
   391  	.cfi_endproc
   392  END(ffi_go_closure_sysv)
   393  
   394  #if defined __ELF__ && defined __linux__
   395  	.section	.note.GNU-stack,"",@progbits
   396  #endif
   397  #endif