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

     1  /* -----------------------------------------------------------------------
     2     darwin.S - Copyright (c) 2000 John Hornkvist
     3  	      Copyright (c) 2004, 2010 Free Software Foundation, 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, EXPRESS
    19     OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    20     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    21     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
    22     OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
    23     ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    24     OTHER DEALINGS IN THE SOFTWARE.
    25     ----------------------------------------------------------------------- */
    26  
    27  #define LIBFFI_ASM
    28  #if defined(__ppc64__)
    29  #define MODE_CHOICE(x, y) y
    30  #else
    31  #define MODE_CHOICE(x, y) x
    32  #endif
    33  
    34  #define machine_choice	MODE_CHOICE(ppc7400,ppc64)
    35  
    36  ; Define some pseudo-opcodes for size-independent load & store of GPRs ...
    37  #define lgu		MODE_CHOICE(lwzu, ldu)
    38  #define lg		MODE_CHOICE(lwz,ld)
    39  #define sg		MODE_CHOICE(stw,std)
    40  #define sgu		MODE_CHOICE(stwu,stdu)
    41  #define sgux		MODE_CHOICE(stwux,stdux)
    42  
    43  ; ... and the size of GPRs and their storage indicator.
    44  #define GPR_BYTES	MODE_CHOICE(4,8)
    45  #define LOG2_GPR_BYTES	MODE_CHOICE(2,3)	/* log2(GPR_BYTES) */
    46  #define g_long		MODE_CHOICE(long, quad)	/* usage is ".g_long" */
    47  
    48  ; From the ABI doc: "Mac OS X ABI Function Call Guide" Version 2009-02-04.
    49  #define LINKAGE_SIZE	MODE_CHOICE(24,48)
    50  #define PARAM_AREA	MODE_CHOICE(32,64)
    51  #define SAVED_LR_OFFSET	MODE_CHOICE(8,16)	/* save position for lr */
    52  
    53  /* If there is any FP stuff we make space for all of the regs.  */
    54  #define SAVED_FPR_COUNT 13
    55  #define FPR_SIZE	8
    56  #define RESULT_BYTES	16
    57  
    58  /* This should be kept in step with the same value in ffi_darwin.c.  */
    59  #define ASM_NEEDS_REGISTERS 4
    60  #define SAVE_REGS_SIZE (ASM_NEEDS_REGISTERS * GPR_BYTES)
    61  
    62  #include <fficonfig.h>
    63  #include <ffi.h>
    64  
    65  #define JUMPTARGET(name) name
    66  #define L(x) x
    67  
    68  	.text
    69  	.align 2
    70  	.globl _ffi_prep_args
    71  
    72  	.align 2
    73  	.globl _ffi_call_DARWIN
    74  
    75  	/* We arrive here with:
    76  	   r3 = ptr to extended cif.
    77  	   r4 = -bytes.
    78  	   r5 = cif flags.
    79  	   r6 = ptr to return value.
    80  	   r7 = fn pointer (user func).
    81  	   r8 = fn pointer (ffi_prep_args).
    82  	   r9 = ffi_type* for the ret val.  */
    83  
    84  _ffi_call_DARWIN:
    85  Lstartcode:
    86  	mr   	r12,r8	/* We only need r12 until the call,
    87  			   so it does not have to be saved.  */
    88  LFB1:
    89  	/* Save the old stack pointer as AP.  */
    90  	mr	r8,r1
    91  LCFI0:
    92  	
    93  	/* Save the retval type in parents frame.  */
    94  	sg	r9,(LINKAGE_SIZE+6*GPR_BYTES)(r8)
    95  
    96  	/* Allocate the stack space we need.  */
    97  	sgux	r1,r1,r4
    98  
    99  	/* Save registers we use.  */
   100  	mflr	r9
   101  	sg	r9,SAVED_LR_OFFSET(r8)
   102  
   103  	sg	r28,-(4 * GPR_BYTES)(r8)	
   104  	sg	r29,-(3 * GPR_BYTES)(r8)
   105  	sg	r30,-(2 * GPR_BYTES)(r8)
   106  	sg	r31,-(    GPR_BYTES)(r8)
   107  
   108  #if !defined(POWERPC_DARWIN)
   109  	/* The TOC slot is reserved in the Darwin ABI and r2 is volatile.  */
   110  	sg	r2,(5 * GPR_BYTES)(r1)
   111  #endif
   112  
   113  LCFI1:
   114  
   115  	/* Save arguments over call.  */
   116  	mr	r31,r5	/* flags,  */
   117  	mr	r30,r6	/* rvalue,  */
   118  	mr	r29,r7	/* function address,  */
   119  	mr	r28,r8	/* our AP.  */
   120  LCFI2:
   121  	/* Call ffi_prep_args. r3 = extended cif, r4 = stack ptr copy.  */
   122  	mr	r4,r1
   123  	li	r9,0
   124  
   125  	mtctr	r12 /* r12 holds address of _ffi_prep_args.  */
   126  	bctrl
   127  
   128  #if !defined(POWERPC_DARWIN)
   129  	/* The TOC slot is reserved in the Darwin ABI and r2 is volatile.  */
   130  	lg     r2,(5 * GPR_BYTES)(r1)
   131  #endif
   132  	/* Now do the call.
   133  	   Set up cr1 with bits 4-7 of the flags.  */
   134  	mtcrf	0x40,r31
   135  	/* Get the address to call into CTR.  */
   136  	mtctr	r29
   137  	/* Load all those argument registers.
   138  	   We have set up a nice stack frame, just load it into registers.  */
   139  	lg     r3, (LINKAGE_SIZE                )(r1)
   140  	lg     r4, (LINKAGE_SIZE +     GPR_BYTES)(r1)
   141  	lg     r5, (LINKAGE_SIZE + 2 * GPR_BYTES)(r1)
   142  	lg     r6, (LINKAGE_SIZE + 3 * GPR_BYTES)(r1)
   143  	nop
   144  	lg     r7, (LINKAGE_SIZE + 4 * GPR_BYTES)(r1)
   145  	lg     r8, (LINKAGE_SIZE + 5 * GPR_BYTES)(r1)
   146  	lg     r9, (LINKAGE_SIZE + 6 * GPR_BYTES)(r1)
   147  	lg     r10,(LINKAGE_SIZE + 7 * GPR_BYTES)(r1)
   148  
   149  L1:
   150  	/* ... Load all the FP registers.  */
   151  	bf	6,L2	/* No floats to load.  */
   152  	lfd	f1, -SAVE_REGS_SIZE-(13*FPR_SIZE)(r28)
   153  	lfd	f2, -SAVE_REGS_SIZE-(12*FPR_SIZE)(r28)
   154  	lfd	f3, -SAVE_REGS_SIZE-(11*FPR_SIZE)(r28)
   155  	lfd	f4, -SAVE_REGS_SIZE-(10*FPR_SIZE)(r28)
   156  	nop
   157  	lfd	f5, -SAVE_REGS_SIZE-( 9*FPR_SIZE)(r28)
   158  	lfd	f6, -SAVE_REGS_SIZE-( 8*FPR_SIZE)(r28)
   159  	lfd	f7, -SAVE_REGS_SIZE-( 7*FPR_SIZE)(r28)
   160  	lfd	f8, -SAVE_REGS_SIZE-( 6*FPR_SIZE)(r28)
   161  	nop
   162  	lfd     f9, -SAVE_REGS_SIZE-( 5*FPR_SIZE)(r28)
   163  	lfd     f10,-SAVE_REGS_SIZE-( 4*FPR_SIZE)(r28)
   164  	lfd     f11,-SAVE_REGS_SIZE-( 3*FPR_SIZE)(r28)
   165  	lfd     f12,-SAVE_REGS_SIZE-( 2*FPR_SIZE)(r28)
   166  	nop
   167  	lfd     f13,-SAVE_REGS_SIZE-( 1*FPR_SIZE)(r28)
   168  
   169  L2:
   170  	mr	r12,r29	/* Put the target address in r12 as specified.  */
   171  	mtctr  	r12
   172  	nop
   173  	nop
   174  
   175  	/* Make the call.  */
   176  	bctrl
   177  
   178  	/* Now, deal with the return value.  */
   179  
   180  	/* m64 structure returns can occupy the same set of registers as
   181  	   would be used to pass such a structure as arg0 - so take care 
   182  	   not to step on any possibly hot regs.  */
   183  
   184  	/* Get the flags.. */
   185  	mtcrf	0x03,r31 ; we need c6 & cr7 now.
   186  	; FLAG_RETURNS_NOTHING also covers struct ret-by-ref.
   187  	bt	30,L(done_return_value)	  ; FLAG_RETURNS_NOTHING
   188  	bf	27,L(scalar_return_value) ; not FLAG_RETURNS_STRUCT
   189  	
   190  	/* OK, so we have a struct.  */
   191  #if defined(__ppc64__)
   192  	bt	31,L(maybe_return_128) ; FLAG_RETURNS_128BITS, special case 
   193  
   194  	/* OK, we have to map the return back to a mem struct.
   195  	   We are about to trample the parents param area, so recover the
   196  	   return type.  r29 is free, since the call is done.  */
   197  	lg	r29,(LINKAGE_SIZE + 6 * GPR_BYTES)(r28)
   198  
   199  	sg	r3, (LINKAGE_SIZE                )(r28)
   200  	sg	r4, (LINKAGE_SIZE +     GPR_BYTES)(r28)
   201  	sg	r5, (LINKAGE_SIZE + 2 * GPR_BYTES)(r28)
   202  	sg	r6, (LINKAGE_SIZE + 3 * GPR_BYTES)(r28)
   203  	nop
   204  	sg	r7, (LINKAGE_SIZE + 4 * GPR_BYTES)(r28)
   205  	sg	r8, (LINKAGE_SIZE + 5 * GPR_BYTES)(r28)
   206  	sg	r9, (LINKAGE_SIZE + 6 * GPR_BYTES)(r28)
   207  	sg	r10,(LINKAGE_SIZE + 7 * GPR_BYTES)(r28)
   208  	/* OK, so do the block move - we trust that memcpy will not trample
   209  	   the fprs...  */
   210  	mr 	r3,r30 ; dest
   211  	addi	r4,r28,LINKAGE_SIZE ; source
   212  	/* The size is a size_t, should be long.  */
   213  	lg	r5,0(r29)
   214  	/* Figure out small structs */
   215  	cmpi	0,r5,4
   216  	bgt	L3	; 1, 2 and 4 bytes have special rules.
   217  	cmpi	0,r5,3
   218  	beq	L3	; not 3
   219  	addi	r4,r4,8
   220  	subf	r4,r5,r4
   221  L3:
   222  	bl	_memcpy
   223  	
   224  	/* ... do we need the FP registers? - recover the flags.. */
   225  	mtcrf	0x03,r31 ; we need c6 & cr7 now.
   226  	bf	29,L(done_return_value)	/* No floats in the struct.  */
   227  	stfd	f1, -SAVE_REGS_SIZE-(13*FPR_SIZE)(r28)
   228  	stfd	f2, -SAVE_REGS_SIZE-(12*FPR_SIZE)(r28)
   229  	stfd	f3, -SAVE_REGS_SIZE-(11*FPR_SIZE)(r28)
   230  	stfd	f4, -SAVE_REGS_SIZE-(10*FPR_SIZE)(r28)
   231  	nop
   232  	stfd	f5, -SAVE_REGS_SIZE-( 9*FPR_SIZE)(r28)
   233  	stfd	f6, -SAVE_REGS_SIZE-( 8*FPR_SIZE)(r28)
   234  	stfd	f7, -SAVE_REGS_SIZE-( 7*FPR_SIZE)(r28)
   235  	stfd	f8, -SAVE_REGS_SIZE-( 6*FPR_SIZE)(r28)
   236  	nop
   237  	stfd	f9, -SAVE_REGS_SIZE-( 5*FPR_SIZE)(r28)
   238  	stfd	f10,-SAVE_REGS_SIZE-( 4*FPR_SIZE)(r28)
   239  	stfd	f11,-SAVE_REGS_SIZE-( 3*FPR_SIZE)(r28)
   240  	stfd	f12,-SAVE_REGS_SIZE-( 2*FPR_SIZE)(r28)
   241  	nop
   242  	stfd	f13,-SAVE_REGS_SIZE-( 1*FPR_SIZE)(r28)
   243  
   244  	mr	r3,r29	; ffi_type *
   245  	mr	r4,r30	; dest
   246  	addi	r5,r28,-SAVE_REGS_SIZE-(13*FPR_SIZE) ; fprs
   247  	xor	r6,r6,r6
   248  	sg	r6,(LINKAGE_SIZE + 7 * GPR_BYTES)(r28)
   249  	addi	r6,r28,(LINKAGE_SIZE + 7 * GPR_BYTES) ; point to a zeroed counter.
   250  	bl 	_darwin64_struct_floats_to_mem
   251  
   252  	b L(done_return_value)
   253  #else
   254  	stw	r3,0(r30) ; m32 the only struct return in reg is 4 bytes.
   255  #endif
   256  	b L(done_return_value)
   257  
   258  L(fp_return_value):
   259  	/* Do we have long double to store?  */
   260  	bf	31,L(fd_return_value) ; FLAG_RETURNS_128BITS
   261  	stfd	f1,0(r30)
   262  	stfd	f2,FPR_SIZE(r30)
   263  	b	L(done_return_value)
   264  
   265  L(fd_return_value):
   266  	/* Do we have double to store?  */
   267  	bf	28,L(float_return_value)
   268  	stfd	f1,0(r30)
   269  	b	L(done_return_value)
   270  
   271  L(float_return_value):
   272  	/* We only have a float to store.  */
   273  	stfs	f1,0(r30)
   274  	b	L(done_return_value)
   275  
   276  L(scalar_return_value):
   277  	bt	29,L(fp_return_value)	; FLAG_RETURNS_FP
   278  	; ffi_arg is defined as unsigned long. 
   279  	sg	r3,0(r30)		; Save the reg.
   280  	bf	28,L(done_return_value) ; not FLAG_RETURNS_64BITS 
   281  
   282  #if defined(__ppc64__)
   283  L(maybe_return_128):
   284  	std	r3,0(r30)
   285  	bf	31,L(done_return_value) ; not FLAG_RETURNS_128BITS 
   286  	std	r4,8(r30)
   287  #else
   288  	stw	r4,4(r30)
   289  #endif
   290  
   291  	/* Fall through.  */
   292  	/* We want this at the end to simplify eh epilog computation.  */
   293  
   294  L(done_return_value):
   295  	/* Restore the registers we used and return.  */
   296  	lg	r29,SAVED_LR_OFFSET(r28)
   297  	; epilog
   298  	lg	r31,-(1 * GPR_BYTES)(r28)
   299  	mtlr	r29
   300  	lg	r30,-(2 * GPR_BYTES)(r28)
   301  	lg	r29,-(3 * GPR_BYTES)(r28)
   302  	lg	r28,-(4 * GPR_BYTES)(r28)
   303  	lg	r1,0(r1)
   304  	blr
   305  LFE1:
   306  	.align	1
   307  /* END(_ffi_call_DARWIN)  */
   308  
   309  /* Provide a null definition of _ffi_call_AIX.  */
   310  	.text
   311  	.globl _ffi_call_AIX
   312  	.align 2
   313  _ffi_call_AIX:
   314  	blr
   315  /* END(_ffi_call_AIX)  */
   316  
   317  /* EH stuff.  */
   318  
   319  #define EH_DATA_ALIGN_FACT MODE_CHOICE(0x7c,0x78)
   320  
   321  	.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
   322  EH_frame1:
   323  	.set	L$set$0,LECIE1-LSCIE1
   324  	.long	L$set$0	; Length of Common Information Entry
   325  LSCIE1:
   326  	.long	0x0	; CIE Identifier Tag
   327  	.byte	0x1	; CIE Version
   328  	.ascii	"zR\0"	; CIE Augmentation
   329  	.byte	0x1	; uleb128 0x1; CIE Code Alignment Factor
   330  	.byte	EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor
   331  	.byte	0x41	; CIE RA Column
   332  	.byte	0x1	; uleb128 0x1; Augmentation size
   333  	.byte	0x10	; FDE Encoding (pcrel)
   334  	.byte	0xc	; DW_CFA_def_cfa
   335  	.byte	0x1	; uleb128 0x1
   336  	.byte	0x0	; uleb128 0x0
   337  	.align	LOG2_GPR_BYTES
   338  LECIE1:
   339  
   340  	.globl _ffi_call_DARWIN.eh
   341  _ffi_call_DARWIN.eh:
   342  LSFDE1:
   343  	.set	L$set$1,LEFDE1-LASFDE1
   344  	.long	L$set$1	; FDE Length
   345  LASFDE1:
   346  	.long	LASFDE1-EH_frame1 ; FDE CIE offset
   347  	.g_long	Lstartcode-.	; FDE initial location
   348  	.set	L$set$3,LFE1-Lstartcode
   349  	.g_long	L$set$3	; FDE address range
   350  	.byte   0x0     ; uleb128 0x0; Augmentation size
   351  	.byte	0x4	; DW_CFA_advance_loc4
   352  	.set	L$set$4,LCFI0-Lstartcode
   353  	.long	L$set$4
   354  	.byte	0xd	; DW_CFA_def_cfa_register
   355  	.byte	0x08	; uleb128 0x08
   356  	.byte	0x4	; DW_CFA_advance_loc4
   357  	.set	L$set$5,LCFI1-LCFI0
   358  	.long	L$set$5
   359  	.byte   0x11    ; DW_CFA_offset_extended_sf
   360  	.byte	0x41	; uleb128 0x41
   361  	.byte   0x7e    ; sleb128 -2
   362  	.byte	0x9f	; DW_CFA_offset, column 0x1f
   363  	.byte	0x1	; uleb128 0x1
   364  	.byte	0x9e	; DW_CFA_offset, column 0x1e
   365  	.byte	0x2	; uleb128 0x2
   366  	.byte	0x9d	; DW_CFA_offset, column 0x1d
   367  	.byte	0x3	; uleb128 0x3
   368  	.byte	0x9c	; DW_CFA_offset, column 0x1c
   369  	.byte	0x4	; uleb128 0x4
   370  	.byte	0x4	; DW_CFA_advance_loc4
   371  	.set	L$set$6,LCFI2-LCFI1
   372  	.long	L$set$6
   373  	.byte	0xd	; DW_CFA_def_cfa_register
   374  	.byte	0x1c	; uleb128 0x1c
   375  	.align LOG2_GPR_BYTES
   376  LEFDE1:
   377  	.align 1
   378