Home | History | Annotate | Download | only in powerpc
      1 #if defined(__ppc__)
      2 
      3 /* -----------------------------------------------------------------------
      4    ppc-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
      5    Inc. based on ppc_closure.S
      6 
      7    PowerPC Assembly glue.
      8 
      9    Permission is hereby granted, free of charge, to any person obtaining
     10    a copy of this software and associated documentation files (the
     11    ``Software''), to deal in the Software without restriction, including
     12    without limitation the rights to use, copy, modify, merge, publish,
     13    distribute, sublicense, and/or sell copies of the Software, and to
     14    permit persons to whom the Software is furnished to do so, subject to
     15    the following conditions:
     16 
     17    The above copyright notice and this permission notice shall be included
     18    in all copies or substantial portions of the Software.
     19 
     20    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
     21    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     22    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     23    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
     24    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     25    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     26    OTHER DEALINGS IN THE SOFTWARE.
     27    ----------------------------------------------------------------------- */
     28 
     29 #define LIBFFI_ASM
     30 
     31 #include <ffi.h>
     32 #include <ppc-ffitarget.h>	// for FFI_TRAMPOLINE_SIZE
     33 #include <ppc-darwin.h>
     34 #include <architecture/ppc/mode_independent_asm.h>
     35 
     36 	.file	"ppc-darwin_closure.S"
     37 .text
     38 	.align	LOG2_GPR_BYTES
     39 	.globl	_ffi_closure_ASM
     40 
     41 .text
     42 	.align	LOG2_GPR_BYTES
     43 
     44 _ffi_closure_ASM:
     45 LFB1:
     46 	mflr	r0					// Save return address
     47 	stg		r0,SF_RETURN(r1)
     48 
     49 LCFI0:
     50 	/* 24/48 bytes (Linkage Area)
     51 	   32/64 bytes (outgoing parameter area, always reserved)
     52 	   104 bytes (13*8 from FPR)
     53 	   16/32 bytes (result)
     54 	   176/232 total bytes  */
     55 
     56 	/*	skip over caller save area and keep stack aligned to 16/32.	*/
     57 	stgu	r1,-SF_ROUND(176)(r1)
     58 
     59 LCFI1:
     60 	/* We want to build up an area for the parameters passed
     61 	   in registers. (both floating point and integer)  */
     62 
     63 	/*	176/256 bytes (callee stack frame aligned to 16/32)
     64 		24/48 bytes (caller linkage area)
     65 		200/304 (start of caller parameter area aligned to 4/8)
     66 	*/
     67 
     68 	/* Save GPRs 3 - 10 (aligned to 4/8)
     69 	   in the parents outgoing area.  */
     70 	stg		r3,200(r1)
     71 	stg		r4,204(r1)
     72 	stg		r5,208(r1)
     73 	stg		r6,212(r1)
     74 	stg		r7,216(r1)
     75 	stg		r8,220(r1)
     76 	stg		r9,224(r1)
     77 	stg		r10,228(r1)
     78 
     79 	/* Save FPRs 1 - 13. (aligned to 8)  */
     80 	stfd	f1,56(r1)
     81 	stfd	f2,64(r1)
     82 	stfd	f3,72(r1)
     83 	stfd	f4,80(r1)
     84 	stfd	f5,88(r1)
     85 	stfd	f6,96(r1)
     86 	stfd	f7,104(r1)
     87 	stfd	f8,112(r1)
     88 	stfd	f9,120(r1)
     89 	stfd	f10,128(r1)
     90 	stfd	f11,136(r1)
     91 	stfd	f12,144(r1)
     92 	stfd	f13,152(r1)
     93 
     94 	// Set up registers for the routine that actually does the work.
     95 	mr		r3,r11		// context pointer from the trampoline
     96 	addi	r4,r1,160	// result storage
     97 	addi	r5,r1,200	// saved GPRs
     98 	addi	r6,r1,56	// saved FPRs
     99 	bl		Lffi_closure_helper_DARWIN$stub
    100 
    101 	/* Now r3 contains the return type. Use it to look up in a table
    102 	   so we know how to deal with each type.  */
    103 	addi	r5,r1,160				// Copy result storage pointer.
    104 	bl		Lget_ret_type0_addr		// Get pointer to Lret_type0 into LR.
    105 	mflr	r4						// Move to r4.
    106 	slwi	r3,r3,4					// Multiply return type by 16.
    107 	add		r3,r3,r4				// Add contents of table to table address.
    108 	mtctr	r3
    109 	bctr
    110 
    111 LFE1:
    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 	nop
    117 	nop
    118 	nop
    119 
    120 Lget_ret_type0_addr:
    121 	blrl
    122 
    123 /* case FFI_TYPE_VOID  */
    124 Lret_type0:
    125 	b		Lfinish
    126 	nop
    127 	nop
    128 	nop
    129 
    130 /* case FFI_TYPE_INT  */
    131 Lret_type1:
    132 	lwz		r3,0(r5)
    133 	b		Lfinish
    134 	nop
    135 	nop
    136 
    137 /* case FFI_TYPE_FLOAT  */
    138 Lret_type2:
    139 	lfs		f1,0(r5)
    140 	b		Lfinish
    141 	nop
    142 	nop
    143 
    144 /* case FFI_TYPE_DOUBLE  */
    145 Lret_type3:
    146 	lfd		f1,0(r5)
    147 	b		Lfinish
    148 	nop
    149 	nop
    150 
    151 /* case FFI_TYPE_LONGDOUBLE  */
    152 Lret_type4:
    153 	lfd		f1,0(r5)
    154 	lfd		f2,8(r5)
    155 	b		Lfinish
    156 	nop
    157 
    158 /* case FFI_TYPE_UINT8  */
    159 Lret_type5:
    160 	lbz		r3,3(r5)
    161 	b		Lfinish
    162 	nop
    163 	nop
    164 
    165 /* case FFI_TYPE_SINT8  */
    166 Lret_type6:
    167 	lbz		r3,3(r5)
    168 	extsb	r3,r3
    169 	b		Lfinish
    170 	nop
    171 
    172 /* case FFI_TYPE_UINT16  */
    173 Lret_type7:
    174 	lhz		r3,2(r5)
    175 	b		Lfinish
    176 	nop
    177 	nop
    178 
    179 /* case FFI_TYPE_SINT16  */
    180 Lret_type8:
    181 	lha		r3,2(r5)
    182 	b		Lfinish
    183 	nop
    184 	nop
    185 
    186 /* case FFI_TYPE_UINT32  */
    187 Lret_type9:		// same as Lret_type1
    188 	lwz		r3,0(r5)
    189 	b		Lfinish
    190 	nop
    191 	nop
    192 
    193 /* case FFI_TYPE_SINT32  */
    194 Lret_type10:	// same as Lret_type1
    195 	lwz		r3,0(r5)
    196 	b		Lfinish
    197 	nop
    198 	nop
    199 
    200 /* case FFI_TYPE_UINT64  */
    201 Lret_type11:
    202 	lwz		r3,0(r5)
    203 	lwz		r4,4(r5)
    204 	b		Lfinish
    205 	nop
    206 
    207 /* case FFI_TYPE_SINT64  */
    208 Lret_type12:	// same as Lret_type11
    209 	lwz		r3,0(r5)
    210 	lwz		r4,4(r5)
    211 	b		Lfinish
    212 	nop
    213 
    214 /* case FFI_TYPE_STRUCT  */
    215 Lret_type13:
    216 	b		Lfinish
    217 	nop
    218 	nop
    219 	nop
    220 
    221 /* End 16-byte aligned cases */
    222 /* case FFI_TYPE_POINTER  */
    223 // This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types
    224 // are added in future, the following code will need to be updated and
    225 // padded to 16 bytes.
    226 Lret_type14:
    227 	lg		r3,0(r5)
    228 	// fall through
    229 
    230 /* case done  */
    231 Lfinish:
    232 	addi	r1,r1,SF_ROUND(176)	// Restore stack pointer.
    233 	lg		r0,SF_RETURN(r1)	// Restore return address.
    234 	mtlr	r0					// Restore link register.
    235 	blr
    236 
    237 /* END(ffi_closure_ASM)  */
    238 
    239 .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
    240 EH_frame1:
    241 	.set	L$set$0,LECIE1-LSCIE1
    242 	.long	L$set$0		; Length of Common Information Entry
    243 LSCIE1:
    244 	.long	0x0			; CIE Identifier Tag
    245 	.byte	0x1			; CIE Version
    246 	.ascii	"zR\0"		; CIE Augmentation
    247 	.byte	0x1			; uleb128 0x1; CIE Code Alignment Factor
    248 	.byte	0x7c		; sleb128 -4; CIE Data Alignment Factor
    249 	.byte	0x41		; CIE RA Column
    250 	.byte	0x1			; uleb128 0x1; Augmentation size
    251 	.byte	0x10		; FDE Encoding (pcrel)
    252 	.byte	0xc			; DW_CFA_def_cfa
    253 	.byte	0x1			; uleb128 0x1
    254 	.byte	0x0			; uleb128 0x0
    255 	.align	LOG2_GPR_BYTES
    256 LECIE1:
    257 .globl _ffi_closure_ASM.eh
    258 _ffi_closure_ASM.eh:
    259 LSFDE1:
    260 	.set	L$set$1,LEFDE1-LASFDE1
    261 	.long	L$set$1		; FDE Length
    262 
    263 LASFDE1:
    264 	.long	LASFDE1-EH_frame1		; FDE CIE offset
    265 	.g_long	LFB1-.					; FDE initial location
    266 	.set	L$set$3,LFE1-LFB1
    267 	.g_long	L$set$3					; FDE address range
    268 	.byte   0x0						; uleb128 0x0; Augmentation size
    269 	.byte	0x4						; DW_CFA_advance_loc4
    270 	.set	L$set$3,LCFI1-LCFI0
    271 	.long	L$set$3
    272 	.byte	0xe						; DW_CFA_def_cfa_offset
    273 	.byte	176,1					; uleb128 176
    274 	.byte	0x4						; DW_CFA_advance_loc4
    275 	.set	L$set$4,LCFI0-LFB1
    276 	.long	L$set$4
    277 	.byte   0x11					; DW_CFA_offset_extended_sf
    278 	.byte	0x41					; uleb128 0x41
    279 	.byte   0x7e					; sleb128 -2
    280 	.align	LOG2_GPR_BYTES
    281 
    282 LEFDE1:
    283 .data
    284 	.align	LOG2_GPR_BYTES
    285 LDFCM0:
    286 .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
    287 	.align	LOG2_GPR_BYTES
    288 
    289 Lffi_closure_helper_DARWIN$stub:
    290 	.indirect_symbol _ffi_closure_helper_DARWIN
    291 	mflr	r0
    292 	bcl		20,31,LO$ffi_closure_helper_DARWIN
    293 
    294 LO$ffi_closure_helper_DARWIN:
    295 	mflr	r11
    296 	addis	r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
    297 	mtlr	r0
    298 	lgu		r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
    299 	mtctr	r12
    300 	bctr
    301 
    302 .lazy_symbol_pointer
    303 L_ffi_closure_helper_DARWIN$lazy_ptr:
    304 	.indirect_symbol _ffi_closure_helper_DARWIN
    305 	.g_long dyld_stub_binding_helper
    306 
    307 
    308 #endif // __ppc__
    309