Home | History | Annotate | Download | only in powerpc
      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 
    379