Home | History | Annotate | Download | only in powerpc
      1 /* -----------------------------------------------------------------------
      2    darwin_closure.S - Copyright (c) 2002, 2003, 2004, 2010,
      3    Free Software Foundation, Inc.
      4    based on ppc_closure.S
      5 
      6    PowerPC Assembly glue.
      7 
      8    Permission is hereby granted, free of charge, to any person obtaining
      9    a copy of this software and associated documentation files (the
     10    ``Software''), to deal in the Software without restriction, including
     11    without limitation the rights to use, copy, modify, merge, publish,
     12    distribute, sublicense, and/or sell copies of the Software, and to
     13    permit persons to whom the Software is furnished to do so, subject to
     14    the following conditions:
     15 
     16    The above copyright notice and this permission notice shall be included
     17    in all copies or substantial portions of the Software.
     18 
     19    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
     20    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     21    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     22    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
     23    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     24    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     25    OTHER DEALINGS IN THE SOFTWARE.
     26    ----------------------------------------------------------------------- */
     27 
     28 #define LIBFFI_ASM
     29 #define L(x) x
     30 
     31 #if defined(__ppc64__)
     32 #define MODE_CHOICE(x, y) y
     33 #else
     34 #define MODE_CHOICE(x, y) x
     35 #endif
     36 
     37 #define machine_choice	MODE_CHOICE(ppc7400,ppc64)
     38 
     39 ; Define some pseudo-opcodes for size-independent load & store of GPRs ...
     40 #define lgu		MODE_CHOICE(lwzu, ldu)
     41 #define lg		MODE_CHOICE(lwz,ld)
     42 #define sg		MODE_CHOICE(stw,std)
     43 #define sgu		MODE_CHOICE(stwu,stdu)
     44 
     45 ; ... and the size of GPRs and their storage indicator.
     46 #define GPR_BYTES	MODE_CHOICE(4,8)
     47 #define LOG2_GPR_BYTES	MODE_CHOICE(2,3)	/* log2(GPR_BYTES) */
     48 #define g_long		MODE_CHOICE(long, quad)	/* usage is ".g_long" */
     49 
     50 ; From the ABI doc: "Mac OS X ABI Function Call Guide" Version 2009-02-04.
     51 #define LINKAGE_SIZE	MODE_CHOICE(24,48)
     52 #define PARAM_AREA	MODE_CHOICE(32,64)
     53 
     54 #define SAVED_CR_OFFSET	MODE_CHOICE(4,8)	/* save position for CR */
     55 #define SAVED_LR_OFFSET	MODE_CHOICE(8,16)	/* save position for lr */
     56 
     57 /* WARNING: if ffi_type is changed... here be monsters.
     58    Offsets of items within the result type.  */
     59 #define FFI_TYPE_TYPE	MODE_CHOICE(6,10)
     60 #define FFI_TYPE_ELEM	MODE_CHOICE(8,16)
     61 
     62 #define SAVED_FPR_COUNT 13
     63 #define FPR_SIZE	8
     64 /* biggest m64 struct ret is 8GPRS + 13FPRS = 168 bytes - rounded to 16bytes = 176. */
     65 #define RESULT_BYTES	MODE_CHOICE(16,176)
     66 
     67 ; The whole stack frame **MUST** be 16byte-aligned.
     68 #define SAVE_SIZE (((LINKAGE_SIZE+PARAM_AREA+SAVED_FPR_COUNT*FPR_SIZE+RESULT_BYTES)+15) & -16LL)
     69 #define PAD_SIZE (SAVE_SIZE-(LINKAGE_SIZE+PARAM_AREA+SAVED_FPR_COUNT*FPR_SIZE+RESULT_BYTES))
     70 
     71 #define PARENT_PARM_BASE (SAVE_SIZE+LINKAGE_SIZE)
     72 #define FP_SAVE_BASE (LINKAGE_SIZE+PARAM_AREA)
     73 
     74 #if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
     75 ; We no longer need the pic symbol stub for Darwin >= 9.
     76 #define BLCLS_HELP _ffi_closure_helper_DARWIN
     77 #define STRUCT_RETVALUE_P _darwin64_struct_ret_by_value_p
     78 #define PASS_STR_FLOATS _darwin64_pass_struct_floats
     79 #undef WANT_STUB
     80 #else
     81 #define BLCLS_HELP L_ffi_closure_helper_DARWIN$stub
     82 #define STRUCT_RETVALUE_P L_darwin64_struct_ret_by_value_p$stub
     83 #define PASS_STR_FLOATS L_darwin64_pass_struct_floats$stub
     84 #define WANT_STUB
     85 #endif
     86 
     87 /* m32/m64
     88 
     89    The stack layout looks like this:
     90 
     91    |   Additional params...			| |     Higher address
     92    ~						~ ~
     93    |   Parameters      (at least 8*4/8=32/64)	| | NUM_GPR_ARG_REGISTERS
     94    |--------------------------------------------| |
     95    |   TOC=R2 (AIX) Reserved (Darwin)   4/8	| |
     96    |--------------------------------------------| |
     97    |   Reserved                       2*4/8	| |
     98    |--------------------------------------------| |
     99    |   Space for callee`s LR		4/8	| |
    100    |--------------------------------------------| |
    101    |   Saved CR [low word for m64]      4/8	| |
    102    |--------------------------------------------| |
    103    |   Current backchain pointer	4/8	|-/ Parent`s frame.
    104    |--------------------------------------------| <+ <<< on entry to
    105    |   Result Bytes		       16/176	| |
    106    |--------------------------------------------| |
    107    ~   padding to 16-byte alignment		~ ~
    108    |--------------------------------------------| |
    109    |   NUM_FPR_ARG_REGISTERS slots		| |
    110    |   here fp13 .. fp1		       13*8	| |
    111    |--------------------------------------------| |
    112    |   R3..R10			  8*4/8=32/64	| | NUM_GPR_ARG_REGISTERS
    113    |--------------------------------------------| |
    114    |   TOC=R2 (AIX) Reserved (Darwin)   4/8	| |
    115    |--------------------------------------------| |	stack	|
    116    |   Reserved [compiler,binder]     2*4/8	| |	grows	|
    117    |--------------------------------------------| |	down	V
    118    |   Space for callees LR		4/8	| |
    119    |--------------------------------------------| |	lower addresses
    120    |   Saved CR [low word for m64]      4/8	| |
    121    |--------------------------------------------| |     stack pointer here
    122    |   Current backchain pointer	4/8	|-/	during
    123    |--------------------------------------------|   <<<	call.
    124 
    125 */
    126 
    127 	.file	"darwin_closure.S"
    128 
    129 	.machine machine_choice
    130 
    131 	.text
    132 	.globl _ffi_closure_ASM
    133 	.align LOG2_GPR_BYTES
    134 _ffi_closure_ASM:
    135 LFB1:
    136 Lstartcode:
    137 	mflr	r0			/* extract return address  */
    138 	sg	r0,SAVED_LR_OFFSET(r1)	/* save the return address  */
    139 LCFI0:
    140 	sgu	r1,-SAVE_SIZE(r1)	/* skip over caller save area
    141 					keep stack aligned to 16.  */
    142 LCFI1:
    143 	/* We want to build up an area for the parameters passed
    144 	   in registers. (both floating point and integer)  */
    145 
    146 	/* Put gpr 3 to gpr 10 in the parents outgoing area...
    147 	   ... the remainder of any params that overflowed the regs will
    148 	   follow here.  */
    149 	sg	r3, (PARENT_PARM_BASE                )(r1)
    150 	sg	r4, (PARENT_PARM_BASE + GPR_BYTES    )(r1)
    151 	sg	r5, (PARENT_PARM_BASE + GPR_BYTES * 2)(r1)
    152 	sg	r6, (PARENT_PARM_BASE + GPR_BYTES * 3)(r1)
    153 	sg	r7, (PARENT_PARM_BASE + GPR_BYTES * 4)(r1)
    154 	sg	r8, (PARENT_PARM_BASE + GPR_BYTES * 5)(r1)
    155 	sg	r9, (PARENT_PARM_BASE + GPR_BYTES * 6)(r1)
    156 	sg	r10,(PARENT_PARM_BASE + GPR_BYTES * 7)(r1)
    157 
    158 	/* We save fpr 1 to fpr 14 in our own save frame.  */
    159 	stfd	f1, (FP_SAVE_BASE                 )(r1)
    160 	stfd	f2, (FP_SAVE_BASE +  FPR_SIZE     )(r1)
    161 	stfd	f3, (FP_SAVE_BASE +  FPR_SIZE * 2 )(r1)
    162 	stfd	f4, (FP_SAVE_BASE +  FPR_SIZE * 3 )(r1)
    163 	stfd	f5, (FP_SAVE_BASE +  FPR_SIZE * 4 )(r1)
    164 	stfd	f6, (FP_SAVE_BASE +  FPR_SIZE * 5 )(r1)
    165 	stfd	f7, (FP_SAVE_BASE +  FPR_SIZE * 6 )(r1)
    166 	stfd	f8, (FP_SAVE_BASE +  FPR_SIZE * 7 )(r1)
    167 	stfd	f9, (FP_SAVE_BASE +  FPR_SIZE * 8 )(r1)
    168 	stfd	f10,(FP_SAVE_BASE +  FPR_SIZE * 9 )(r1)
    169 	stfd	f11,(FP_SAVE_BASE +  FPR_SIZE * 10)(r1)
    170 	stfd	f12,(FP_SAVE_BASE +  FPR_SIZE * 11)(r1)
    171 	stfd	f13,(FP_SAVE_BASE +  FPR_SIZE * 12)(r1)
    172 
    173 	/* Set up registers for the routine that actually does the work
    174 	   get the context pointer from the trampoline.  */
    175 	mr	r3,r11
    176 
    177 	/* Now load up the pointer to the result storage.  */
    178 	addi	r4,r1,(SAVE_SIZE-RESULT_BYTES)
    179 
    180 	/* Now load up the pointer to the saved gpr registers.  */
    181 	addi	r5,r1,PARENT_PARM_BASE
    182 
    183 	/* Now load up the pointer to the saved fpr registers.  */
    184 	addi	r6,r1,FP_SAVE_BASE
    185 
    186 	/* Make the call.  */
    187 	bl	BLCLS_HELP
    188 
    189 	/* r3 contains the rtype pointer... save it since we will need
    190 	   it later.  */
    191 	sg	r3,LINKAGE_SIZE(r1)	; ffi_type * result_type
    192 	lg	r0,0(r3)		; size => r0
    193 	lhz	r3,FFI_TYPE_TYPE(r3)	; type => r3
    194 
    195 	/* The helper will have intercepted structure returns and inserted
    196 	   the caller`s destination address for structs returned by ref.  */
    197 
    198 	/* r3 contains the return type  so use it to look up in a table
    199 	   so we know how to deal with each type.  */
    200 
    201 	addi	r5,r1,(SAVE_SIZE-RESULT_BYTES) /* Otherwise, our return is here.  */
    202 	bl	Lget_ret_type0_addr	/* Get pointer to Lret_type0 into LR.  */
    203 	mflr	r4			/* Move to r4.  */
    204 	slwi	r3,r3,4			/* Now multiply return type by 16.  */
    205 	add	r3,r3,r4		/* Add contents of table to table address.  */
    206 	mtctr	r3
    207 	bctr			 	 /* Jump to it.  */
    208 LFE1:
    209 /* Each of the ret_typeX code fragments has to be exactly 16 bytes long
    210    (4 instructions). For cache effectiveness we align to a 16 byte boundary
    211    first.  */
    212 
    213 	.align 4
    214 
    215 	nop
    216 	nop
    217 	nop
    218 Lget_ret_type0_addr:
    219 	blrl
    220 
    221 /* case FFI_TYPE_VOID  */
    222 Lret_type0:
    223 	b	Lfinish
    224 	nop
    225 	nop
    226 	nop
    227 
    228 /* case FFI_TYPE_INT  */
    229 Lret_type1:
    230 	lg	r3,0(r5)
    231 	b	Lfinish
    232 	nop
    233 	nop
    234 
    235 /* case FFI_TYPE_FLOAT  */
    236 Lret_type2:
    237 	lfs	f1,0(r5)
    238 	b	Lfinish
    239 	nop
    240 	nop
    241 
    242 /* case FFI_TYPE_DOUBLE  */
    243 Lret_type3:
    244 	lfd	f1,0(r5)
    245 	b	Lfinish
    246 	nop
    247 	nop
    248 
    249 /* case FFI_TYPE_LONGDOUBLE  */
    250 Lret_type4:
    251 	lfd	f1,0(r5)
    252 	lfd	f2,8(r5)
    253 	b	Lfinish
    254 	nop
    255 
    256 /* case FFI_TYPE_UINT8  */
    257 Lret_type5:
    258 #if defined(__ppc64__)
    259 	lbz	r3,7(r5)
    260 #else
    261 	lbz	r3,3(r5)
    262 #endif
    263 	b	Lfinish
    264 	nop
    265 	nop
    266 
    267 /* case FFI_TYPE_SINT8  */
    268 Lret_type6:
    269 #if defined(__ppc64__)
    270 	lbz	r3,7(r5)
    271 #else
    272 	lbz	r3,3(r5)
    273 #endif
    274 	extsb	r3,r3
    275 	b	Lfinish
    276 	nop
    277 
    278 /* case FFI_TYPE_UINT16  */
    279 Lret_type7:
    280 #if defined(__ppc64__)
    281 	lhz	r3,6(r5)
    282 #else
    283 	lhz	r3,2(r5)
    284 #endif
    285 	b	Lfinish
    286 	nop
    287 	nop
    288 
    289 /* case FFI_TYPE_SINT16  */
    290 Lret_type8:
    291 #if defined(__ppc64__)
    292 	lha	r3,6(r5)
    293 #else
    294 	lha	r3,2(r5)
    295 #endif
    296 	b	Lfinish
    297 	nop
    298 	nop
    299 
    300 /* case FFI_TYPE_UINT32  */
    301 Lret_type9:
    302 #if defined(__ppc64__)
    303 	lwz	r3,4(r5)
    304 #else
    305 	lwz	r3,0(r5)
    306 #endif
    307 	b	Lfinish
    308 	nop
    309 	nop
    310 
    311 /* case FFI_TYPE_SINT32  */
    312 Lret_type10:
    313 #if defined(__ppc64__)
    314 	lwz	r3,4(r5)
    315 #else
    316 	lwz	r3,0(r5)
    317 #endif
    318 	b	Lfinish
    319 	nop
    320 	nop
    321 
    322 /* case FFI_TYPE_UINT64  */
    323 Lret_type11:
    324 #if defined(__ppc64__)
    325 	lg	r3,0(r5)
    326 	b	Lfinish
    327 	nop
    328 #else
    329 	lwz	r3,0(r5)
    330 	lwz	r4,4(r5)
    331 	b	Lfinish
    332 #endif
    333 	nop
    334 
    335 /* case FFI_TYPE_SINT64  */
    336 Lret_type12:
    337 #if defined(__ppc64__)
    338 	lg	r3,0(r5)
    339 	b	Lfinish
    340 	nop
    341 #else
    342 	lwz	r3,0(r5)
    343 	lwz	r4,4(r5)
    344 	b	Lfinish
    345 #endif
    346 	nop
    347 
    348 /* case FFI_TYPE_STRUCT  */
    349 Lret_type13:
    350 #if defined(__ppc64__)
    351 	lg	r3,0(r5)		; we need at least this...
    352 	cmpi	0,r0,4
    353 	bgt	Lstructend		; not a special small case
    354 	b	Lsmallstruct		; see if we need more.
    355 #else
    356 	cmpi	0,r0,4
    357 	bgt	Lfinish		; not by value
    358 	lg	r3,0(r5)
    359 	b	Lfinish
    360 #endif
    361 /* case FFI_TYPE_POINTER  */
    362 Lret_type14:
    363 	lg	r3,0(r5)
    364 	b	Lfinish
    365 	nop
    366 	nop
    367 
    368 #if defined(__ppc64__)
    369 Lsmallstruct:
    370 	beq	Lfour			; continuation of Lret13.
    371 	cmpi	0,r0,3
    372 	beq	Lfinish			; don`t adjust this - can`t be any floats here...
    373 	srdi	r3,r3,48
    374 	cmpi	0,r0,2
    375 	beq	Lfinish			; .. or here ..
    376 	srdi	r3,r3,8
    377 	b 	Lfinish			; .. or here.
    378 
    379 Lfour:
    380 	lg	r6,LINKAGE_SIZE(r1)	; get the result type
    381 	lg	r6,FFI_TYPE_ELEM(r6)	; elements array pointer
    382 	lg	r6,0(r6)		; first element
    383 	lhz	r0,FFI_TYPE_TYPE(r6)	; OK go the type
    384 	cmpi	0,r0,2			; FFI_TYPE_FLOAT
    385 	bne	Lfourint
    386 	lfs	f1,0(r5)		; just one float in the struct.
    387 	b 	Lfinish
    388 
    389 Lfourint:
    390 	srdi	r3,r3,32		; four bytes.
    391 	b 	Lfinish
    392 
    393 Lstructend:
    394 	lg	r3,LINKAGE_SIZE(r1)	; get the result type
    395 	bl	STRUCT_RETVALUE_P
    396 	cmpi	0,r3,0
    397 	beq	Lfinish			; nope.
    398 	/* Recover a pointer to the results.  */
    399 	addi	r11,r1,(SAVE_SIZE-RESULT_BYTES)
    400 	lg	r3,0(r11)		; we need at least this...
    401 	lg	r4,8(r11)
    402 	cmpi	0,r0,16
    403 	beq	Lfinish		; special case 16 bytes we don't consider floats.
    404 
    405 	/* OK, frustratingly, the process of saving the struct to mem might have
    406 	   messed with the FPRs, so we have to re-load them :(.
    407 	   We`ll use our FPRs space again - calling:
    408 	   void darwin64_pass_struct_floats (ffi_type *s, char *src,
    409 					     unsigned *nfpr, double **fprs)
    410 	   We`ll temporarily pinch the first two slots of the param area for local
    411 	   vars used by the routine.  */
    412 	xor	r6,r6,r6
    413 	addi	r5,r1,PARENT_PARM_BASE		; some space
    414 	sg	r6,0(r5)			; *nfpr zeroed.
    415 	addi	r6,r5,8				; **fprs
    416 	addi	r3,r1,FP_SAVE_BASE		; pointer to FPRs space
    417 	sg	r3,0(r6)
    418 	mr	r4,r11				; the struct is here...
    419 	lg	r3,LINKAGE_SIZE(r1)		; ffi_type * result_type.
    420 	bl	PASS_STR_FLOATS			; get struct floats into FPR save space.
    421 	/* See if we used any floats  */
    422 	lwz	r0,(SAVE_SIZE-RESULT_BYTES)(r1)
    423 	cmpi	0,r0,0
    424 	beq	Lstructints			; nope.
    425 	/* OK load `em up... */
    426 	lfd	f1, (FP_SAVE_BASE                 )(r1)
    427 	lfd	f2, (FP_SAVE_BASE +  FPR_SIZE     )(r1)
    428 	lfd	f3, (FP_SAVE_BASE +  FPR_SIZE * 2 )(r1)
    429 	lfd	f4, (FP_SAVE_BASE +  FPR_SIZE * 3 )(r1)
    430 	lfd	f5, (FP_SAVE_BASE +  FPR_SIZE * 4 )(r1)
    431 	lfd	f6, (FP_SAVE_BASE +  FPR_SIZE * 5 )(r1)
    432 	lfd	f7, (FP_SAVE_BASE +  FPR_SIZE * 6 )(r1)
    433 	lfd	f8, (FP_SAVE_BASE +  FPR_SIZE * 7 )(r1)
    434 	lfd	f9, (FP_SAVE_BASE +  FPR_SIZE * 8 )(r1)
    435 	lfd	f10,(FP_SAVE_BASE +  FPR_SIZE * 9 )(r1)
    436 	lfd	f11,(FP_SAVE_BASE +  FPR_SIZE * 10)(r1)
    437 	lfd	f12,(FP_SAVE_BASE +  FPR_SIZE * 11)(r1)
    438 	lfd	f13,(FP_SAVE_BASE +  FPR_SIZE * 12)(r1)
    439 
    440 	/* point back at our saved struct.  */
    441 Lstructints:
    442 	addi	r11,r1,(SAVE_SIZE-RESULT_BYTES)
    443 	lg	r3,0(r11)			; we end up picking the
    444 	lg	r4,8(r11)			; first two again.
    445 	lg	r5,16(r11)
    446 	lg	r6,24(r11)
    447 	lg	r7,32(r11)
    448 	lg	r8,40(r11)
    449 	lg	r9,48(r11)
    450 	lg	r10,56(r11)
    451 #endif
    452 
    453 /* case done  */
    454 Lfinish:
    455 	addi	r1,r1,SAVE_SIZE		/* Restore stack pointer.  */
    456 	lg	r0,SAVED_LR_OFFSET(r1)	/* Get return address.  */
    457 	mtlr	r0			/* Reset link register.  */
    458 	blr
    459 Lendcode:
    460 	.align 1
    461 
    462 /* END(ffi_closure_ASM)  */
    463 
    464 /* EH frame stuff.  */
    465 #define EH_DATA_ALIGN_FACT MODE_CHOICE(0x7c,0x78)
    466 /* 176, 400 */
    467 #define EH_FRAME_OFFSETA MODE_CHOICE(176,0x90)
    468 #define EH_FRAME_OFFSETB MODE_CHOICE(1,3)
    469 
    470 	.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
    471 EH_frame1:
    472 	.set	L$set$0,LECIE1-LSCIE1
    473 	.long	L$set$0	; Length of Common Information Entry
    474 LSCIE1:
    475 	.long	0x0	; CIE Identifier Tag
    476 	.byte	0x1	; CIE Version
    477 	.ascii	"zR\0"	; CIE Augmentation
    478 	.byte	0x1	; uleb128 0x1; CIE Code Alignment Factor
    479 	.byte	EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor
    480 	.byte	0x41	; CIE RA Column
    481 	.byte	0x1	; uleb128 0x1; Augmentation size
    482 	.byte	0x10	; FDE Encoding (pcrel)
    483 	.byte	0xc	; DW_CFA_def_cfa
    484 	.byte	0x1	; uleb128 0x1
    485 	.byte	0x0	; uleb128 0x0
    486 	.align	LOG2_GPR_BYTES
    487 LECIE1:
    488 	.globl _ffi_closure_ASM.eh
    489 _ffi_closure_ASM.eh:
    490 LSFDE1:
    491 	.set	L$set$1,LEFDE1-LASFDE1
    492 	.long	L$set$1	; FDE Length
    493 
    494 LASFDE1:
    495 	.long	LASFDE1-EH_frame1	; FDE CIE offset
    496 	.g_long	Lstartcode-.	; FDE initial location
    497 	.set	L$set$3,LFE1-Lstartcode
    498 	.g_long	L$set$3	; FDE address range
    499 	.byte   0x0     ; uleb128 0x0; Augmentation size
    500 	.byte	0x4	; DW_CFA_advance_loc4
    501 	.set	L$set$3,LCFI1-LCFI0
    502 	.long	L$set$3
    503 	.byte	0xe	; DW_CFA_def_cfa_offset
    504 	.byte	EH_FRAME_OFFSETA,EH_FRAME_OFFSETB	; uleb128 176,1/190,3
    505 	.byte	0x4	; DW_CFA_advance_loc4
    506 	.set	L$set$4,LCFI0-Lstartcode
    507 	.long	L$set$4
    508 	.byte   0x11    ; DW_CFA_offset_extended_sf
    509 	.byte	0x41	; uleb128 0x41
    510 	.byte   0x7e    ; sleb128 -2
    511 	.align	LOG2_GPR_BYTES
    512 LEFDE1:
    513 	.align 	1
    514 
    515 #ifdef WANT_STUB
    516 	.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
    517 	.align 5
    518 L_ffi_closure_helper_DARWIN$stub:
    519 	.indirect_symbol _ffi_closure_helper_DARWIN
    520 	mflr r0
    521 	bcl 20,31,"L1$spb"
    522 "L1$spb":
    523 	mflr r11
    524 	addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr-"L1$spb")
    525 	mtlr r0
    526 	lwzu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr-"L1$spb")(r11)
    527 	mtctr r12
    528 	bctr
    529 	.lazy_symbol_pointer
    530 L_ffi_closure_helper_DARWIN$lazy_ptr:
    531 	.indirect_symbol _ffi_closure_helper_DARWIN
    532 	.g_long	dyld_stub_binding_helper
    533 
    534 #if defined(__ppc64__)
    535 	.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
    536 	.align 5
    537 L_darwin64_struct_ret_by_value_p$stub:
    538 	.indirect_symbol _darwin64_struct_ret_by_value_p
    539 	mflr r0
    540 	bcl 20,31,"L2$spb"
    541 "L2$spb":
    542 	mflr r11
    543 	addis r11,r11,ha16(L_darwin64_struct_ret_by_value_p$lazy_ptr-"L2$spb")
    544 	mtlr r0
    545 	lwzu r12,lo16(L_darwin64_struct_ret_by_value_p$lazy_ptr-"L2$spb")(r11)
    546 	mtctr r12
    547 	bctr
    548 	.lazy_symbol_pointer
    549 L_darwin64_struct_ret_by_value_p$lazy_ptr:
    550 	.indirect_symbol _darwin64_struct_ret_by_value_p
    551 	.g_long	dyld_stub_binding_helper
    552 
    553 	.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
    554 	.align 5
    555 L_darwin64_pass_struct_floats$stub:
    556 	.indirect_symbol _darwin64_pass_struct_floats
    557 	mflr r0
    558 	bcl 20,31,"L3$spb"
    559 "L3$spb":
    560 	mflr r11
    561 	addis r11,r11,ha16(L_darwin64_pass_struct_floats$lazy_ptr-"L3$spb")
    562 	mtlr r0
    563 	lwzu r12,lo16(L_darwin64_pass_struct_floats$lazy_ptr-"L3$spb")(r11)
    564 	mtctr r12
    565 	bctr
    566 	.lazy_symbol_pointer
    567 L_darwin64_pass_struct_floats$lazy_ptr:
    568 	.indirect_symbol _darwin64_pass_struct_floats
    569 	.g_long	dyld_stub_binding_helper
    570 #  endif
    571 #endif
    572