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