github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libffi/src/powerpc/linux64.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  
    28  #define LIBFFI_ASM
    29  #include <fficonfig.h>
    30  #include <ffi.h>
    31  
    32  #ifdef POWERPC64
    33  	.hidden	ffi_call_LINUX64
    34  	.globl	ffi_call_LINUX64
    35  	.text
    36  	.cfi_startproc
    37  # if _CALL_ELF == 2
    38  ffi_call_LINUX64:
    39  	addis	%r2, %r12, .TOC.-ffi_call_LINUX64@ha
    40  	addi	%r2, %r2, .TOC.-ffi_call_LINUX64@l
    41  	.localentry ffi_call_LINUX64, . - ffi_call_LINUX64
    42  # else
    43  	.section	".opd","aw"
    44  	.align	3
    45  ffi_call_LINUX64:
    46  #  ifdef _CALL_LINUX
    47  	.quad	.L.ffi_call_LINUX64,.TOC.@tocbase,0
    48  	.type	ffi_call_LINUX64,@function
    49  	.text
    50  .L.ffi_call_LINUX64:
    51  #  else
    52  	.hidden	.ffi_call_LINUX64
    53  	.globl	.ffi_call_LINUX64
    54  	.quad	.ffi_call_LINUX64,.TOC.@tocbase,0
    55  	.size	ffi_call_LINUX64,24
    56  	.type	.ffi_call_LINUX64,@function
    57  	.text
    58  .ffi_call_LINUX64:
    59  #  endif
    60  # endif
    61  	mflr	%r0
    62  	std	%r28, -32(%r1)
    63  	std	%r29, -24(%r1)
    64  	std	%r30, -16(%r1)
    65  	std	%r31, -8(%r1)
    66  	std	%r7, 8(%r1)	/* closure, saved in cr field.  */
    67  	std	%r0, 16(%r1)
    68  
    69  	mr	%r28, %r1	/* our AP.  */
    70  	.cfi_def_cfa_register 28
    71  	.cfi_offset 65, 16
    72  	.cfi_offset 31, -8
    73  	.cfi_offset 30, -16
    74  	.cfi_offset 29, -24
    75  	.cfi_offset 28, -32
    76  
    77  	stdux	%r1, %r1, %r8
    78  	mr	%r31, %r6	/* flags, */
    79  	mr	%r30, %r5	/* rvalue, */
    80  	mr	%r29, %r4	/* function address.  */
    81  /* Save toc pointer, not for the ffi_prep_args64 call, but for the later
    82     bctrl function call.  */
    83  # if _CALL_ELF == 2
    84  	std	%r2, 24(%r1)
    85  # else
    86  	std	%r2, 40(%r1)
    87  # endif
    88  
    89  	/* Call ffi_prep_args64.  */
    90  	mr	%r4, %r1
    91  # if defined _CALL_LINUX || _CALL_ELF == 2
    92  	bl	ffi_prep_args64
    93  # else
    94  	bl	.ffi_prep_args64
    95  # endif
    96  
    97  # if _CALL_ELF == 2
    98  	mr	%r12, %r29
    99  # else
   100  	ld	%r12, 0(%r29)
   101  	ld	%r2, 8(%r29)
   102  # endif
   103  	/* Now do the call.  */
   104  	/* Set up cr1 with bits 4-7 of the flags.  */
   105  	mtcrf	0x40, %r31
   106  
   107  	/* Get the address to call into CTR.  */
   108  	mtctr	%r12
   109  	/* Load all those argument registers.  */
   110  	ld	%r3, -32-(8*8)(%r28)
   111  	ld	%r4, -32-(7*8)(%r28)
   112  	ld	%r5, -32-(6*8)(%r28)
   113  	ld	%r6, -32-(5*8)(%r28)
   114  	bf-	5, 1f
   115  	ld	%r7, -32-(4*8)(%r28)
   116  	ld	%r8, -32-(3*8)(%r28)
   117  	ld	%r9, -32-(2*8)(%r28)
   118  	ld	%r10, -32-(1*8)(%r28)
   119  1:
   120  
   121  	/* Load all the FP registers.  */
   122  	bf-	6, 2f
   123  	lfd	%f1, -32-(21*8)(%r28)
   124  	lfd	%f2, -32-(20*8)(%r28)
   125  	lfd	%f3, -32-(19*8)(%r28)
   126  	lfd	%f4, -32-(18*8)(%r28)
   127  	lfd	%f5, -32-(17*8)(%r28)
   128  	lfd	%f6, -32-(16*8)(%r28)
   129  	lfd	%f7, -32-(15*8)(%r28)
   130  	lfd	%f8, -32-(14*8)(%r28)
   131  	lfd	%f9, -32-(13*8)(%r28)
   132  	lfd	%f10, -32-(12*8)(%r28)
   133  	lfd	%f11, -32-(11*8)(%r28)
   134  	lfd	%f12, -32-(10*8)(%r28)
   135  	lfd	%f13, -32-(9*8)(%r28)
   136  2:
   137  
   138  	/* Make the call.  */
   139  	ld	%r11, 8(%r28)
   140  	bctrl
   141  
   142  	/* This must follow the call immediately, the unwinder
   143  	   uses this to find out if r2 has been saved or not.  */
   144  # if _CALL_ELF == 2
   145  	ld	%r2, 24(%r1)
   146  # else
   147  	ld	%r2, 40(%r1)
   148  # endif
   149  
   150  	/* Now, deal with the return value.  */
   151  	mtcrf	0x01, %r31
   152  	bt	31, .Lstruct_return_value
   153  	bt	30, .Ldone_return_value
   154  	bt	29, .Lfp_return_value
   155  	std	%r3, 0(%r30)
   156  	/* Fall through...  */
   157  
   158  .Ldone_return_value:
   159  	/* Restore the registers we used and return.  */
   160  	mr	%r1, %r28
   161  	.cfi_def_cfa_register 1
   162  	ld	%r0, 16(%r28)
   163  	ld	%r28, -32(%r28)
   164  	mtlr	%r0
   165  	ld	%r29, -24(%r1)
   166  	ld	%r30, -16(%r1)
   167  	ld	%r31, -8(%r1)
   168  	blr
   169  
   170  .Lfp_return_value:
   171  	.cfi_def_cfa_register 28
   172  	bf	28, .Lfloat_return_value
   173  	stfd	%f1, 0(%r30)
   174  	mtcrf	0x02, %r31 /* cr6  */
   175  	bf	27, .Ldone_return_value
   176  	stfd	%f2, 8(%r30)
   177  	b	.Ldone_return_value
   178  .Lfloat_return_value:
   179  	stfs	%f1, 0(%r30)
   180  	b	.Ldone_return_value
   181  
   182  .Lstruct_return_value:
   183  	bf	29, .Lsmall_struct
   184  	bf	28, .Lfloat_homog_return_value
   185  	stfd	%f1, 0(%r30)
   186  	stfd	%f2, 8(%r30)
   187  	stfd	%f3, 16(%r30)
   188  	stfd	%f4, 24(%r30)
   189  	stfd	%f5, 32(%r30)
   190  	stfd	%f6, 40(%r30)
   191  	stfd	%f7, 48(%r30)
   192  	stfd	%f8, 56(%r30)
   193  	b	.Ldone_return_value
   194  
   195  .Lfloat_homog_return_value:
   196  	stfs	%f1, 0(%r30)
   197  	stfs	%f2, 4(%r30)
   198  	stfs	%f3, 8(%r30)
   199  	stfs	%f4, 12(%r30)
   200  	stfs	%f5, 16(%r30)
   201  	stfs	%f6, 20(%r30)
   202  	stfs	%f7, 24(%r30)
   203  	stfs	%f8, 28(%r30)
   204  	b	.Ldone_return_value
   205  
   206  .Lsmall_struct:
   207  	std	%r3, 0(%r30)
   208  	std	%r4, 8(%r30)
   209  	b	.Ldone_return_value
   210  
   211  	.cfi_endproc
   212  # if _CALL_ELF == 2
   213  	.size	ffi_call_LINUX64,.-ffi_call_LINUX64
   214  # else
   215  #  ifdef _CALL_LINUX
   216  	.size	ffi_call_LINUX64,.-.L.ffi_call_LINUX64
   217  #  else
   218  	.long	0
   219  	.byte	0,12,0,1,128,4,0,0
   220  	.size	.ffi_call_LINUX64,.-.ffi_call_LINUX64
   221  #  endif
   222  # endif
   223  
   224  #endif
   225  
   226  #if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
   227  	.section	.note.GNU-stack,"",@progbits
   228  #endif