1d4c9320412177895f598a93d73a0e654db27c351Thomas Heller/* -----------------------------------------------------------------------
2d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   darwin.S - Copyright (c) 2000 John Hornkvist
32a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	      Copyright (c) 2004, 2010 Free Software Foundation, Inc.
4d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
5d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   PowerPC Assembly glue.
6d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
7d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   Permission is hereby granted, free of charge, to any person obtaining
8d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   a copy of this software and associated documentation files (the
9d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   ``Software''), to deal in the Software without restriction, including
10d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   without limitation the rights to use, copy, modify, merge, publish,
11d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   distribute, sublicense, and/or sell copies of the Software, and to
12d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   permit persons to whom the Software is furnished to do so, subject to
13d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   the following conditions:
14d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
15d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   The above copyright notice and this permission notice shall be included
16d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   in all copies or substantial portions of the Software.
17d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
18d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
19d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
22d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   OTHER DEALINGS IN THE SOFTWARE.
25d4c9320412177895f598a93d73a0e654db27c351Thomas Heller   ----------------------------------------------------------------------- */
26d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
272a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define LIBFFI_ASM
28d4c9320412177895f598a93d73a0e654db27c351Thomas Heller#if defined(__ppc64__)
29d4c9320412177895f598a93d73a0e654db27c351Thomas Heller#define MODE_CHOICE(x, y) y
30d4c9320412177895f598a93d73a0e654db27c351Thomas Heller#else
31d4c9320412177895f598a93d73a0e654db27c351Thomas Heller#define MODE_CHOICE(x, y) x
32d4c9320412177895f598a93d73a0e654db27c351Thomas Heller#endif
33d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
342a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define machine_choice	MODE_CHOICE(ppc7400,ppc64)
35d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
362a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com; Define some pseudo-opcodes for size-independent load & store of GPRs ...
372a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define lgu		MODE_CHOICE(lwzu, ldu)
382a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define lg		MODE_CHOICE(lwz,ld)
392a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define sg		MODE_CHOICE(stw,std)
402a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define sgu		MODE_CHOICE(stwu,stdu)
412a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define sgux		MODE_CHOICE(stwux,stdux)
422a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
432a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com; ... and the size of GPRs and their storage indicator.
442a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define GPR_BYTES	MODE_CHOICE(4,8)
452a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define LOG2_GPR_BYTES	MODE_CHOICE(2,3)	/* log2(GPR_BYTES) */
462a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define g_long		MODE_CHOICE(long, quad)	/* usage is ".g_long" */
472a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
482a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com; From the ABI doc: "Mac OS X ABI Function Call Guide" Version 2009-02-04.
492a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define LINKAGE_SIZE	MODE_CHOICE(24,48)
502a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define PARAM_AREA	MODE_CHOICE(32,64)
512a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define SAVED_LR_OFFSET	MODE_CHOICE(8,16)	/* save position for lr */
522a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
532a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com/* If there is any FP stuff we make space for all of the regs.  */
542a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define SAVED_FPR_COUNT 13
552a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define FPR_SIZE	8
562a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define RESULT_BYTES	16
572a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
582a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com/* This should be kept in step with the same value in ffi_darwin.c.  */
592a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define ASM_NEEDS_REGISTERS 4
602a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define SAVE_REGS_SIZE (ASM_NEEDS_REGISTERS * GPR_BYTES)
61d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
62d4c9320412177895f598a93d73a0e654db27c351Thomas Heller#include <fficonfig.h>
63d4c9320412177895f598a93d73a0e654db27c351Thomas Heller#include <ffi.h>
642a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
65d4c9320412177895f598a93d73a0e654db27c351Thomas Heller#define JUMPTARGET(name) name
66d4c9320412177895f598a93d73a0e654db27c351Thomas Heller#define L(x) x
67d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
682a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	.text
69d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.align 2
702a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	.globl _ffi_prep_args
712a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
72d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.align 2
732a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	.globl _ffi_call_DARWIN
742a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
752a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	/* We arrive here with:
762a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	   r3 = ptr to extended cif.
772a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	   r4 = -bytes.
782a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	   r5 = cif flags.
792a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	   r6 = ptr to return value.
802a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	   r7 = fn pointer (user func).
812a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	   r8 = fn pointer (ffi_prep_args).
822a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	   r9 = ffi_type* for the ret val.  */
832a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
84d4c9320412177895f598a93d73a0e654db27c351Thomas Heller_ffi_call_DARWIN:
852a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.comLstartcode:
86d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	mr   	r12,r8	/* We only need r12 until the call,
872a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com			   so it does not have to be saved.  */
88d4c9320412177895f598a93d73a0e654db27c351Thomas HellerLFB1:
89d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	/* Save the old stack pointer as AP.  */
90d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	mr	r8,r1
91d4c9320412177895f598a93d73a0e654db27c351Thomas HellerLCFI0:
922a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
932a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	/* Save the retval type in parents frame.  */
942a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	sg	r9,(LINKAGE_SIZE+6*GPR_BYTES)(r8)
952a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
96d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	/* Allocate the stack space we need.  */
972a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	sgux	r1,r1,r4
98d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
99d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	/* Save registers we use.  */
100d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	mflr	r9
1012a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	sg	r9,SAVED_LR_OFFSET(r8)
1022a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
1032a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	sg	r28,-(4 * GPR_BYTES)(r8)
1042a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	sg	r29,-(3 * GPR_BYTES)(r8)
1052a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	sg	r30,-(2 * GPR_BYTES)(r8)
1062a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	sg	r31,-(    GPR_BYTES)(r8)
107d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
1082a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#if !defined(POWERPC_DARWIN)
1092a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	/* The TOC slot is reserved in the Darwin ABI and r2 is volatile.  */
1102a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	sg	r2,(5 * GPR_BYTES)(r1)
1112a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#endif
112d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
113d4c9320412177895f598a93d73a0e654db27c351Thomas HellerLCFI1:
114d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
115d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	/* Save arguments over call.  */
116d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	mr	r31,r5	/* flags,  */
117d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	mr	r30,r6	/* rvalue,  */
118d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	mr	r29,r7	/* function address,  */
119d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	mr	r28,r8	/* our AP.  */
120d4c9320412177895f598a93d73a0e654db27c351Thomas HellerLCFI2:
1212a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	/* Call ffi_prep_args. r3 = extended cif, r4 = stack ptr copy.  */
122d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	mr	r4,r1
123d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	li	r9,0
124d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
125d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	mtctr	r12 /* r12 holds address of _ffi_prep_args.  */
126d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	bctrl
127d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
1282a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#if !defined(POWERPC_DARWIN)
1292a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	/* The TOC slot is reserved in the Darwin ABI and r2 is volatile.  */
1302a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lg     r2,(5 * GPR_BYTES)(r1)
1312a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#endif
132d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	/* Now do the call.
133d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	   Set up cr1 with bits 4-7 of the flags.  */
134d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	mtcrf	0x40,r31
135d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	/* Get the address to call into CTR.  */
136d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	mtctr	r29
137d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	/* Load all those argument registers.
138d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	   We have set up a nice stack frame, just load it into registers.  */
1392a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lg     r3, (LINKAGE_SIZE                )(r1)
1402a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lg     r4, (LINKAGE_SIZE +     GPR_BYTES)(r1)
1412a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lg     r5, (LINKAGE_SIZE + 2 * GPR_BYTES)(r1)
1422a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lg     r6, (LINKAGE_SIZE + 3 * GPR_BYTES)(r1)
143d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	nop
1442a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lg     r7, (LINKAGE_SIZE + 4 * GPR_BYTES)(r1)
1452a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lg     r8, (LINKAGE_SIZE + 5 * GPR_BYTES)(r1)
1462a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lg     r9, (LINKAGE_SIZE + 6 * GPR_BYTES)(r1)
1472a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lg     r10,(LINKAGE_SIZE + 7 * GPR_BYTES)(r1)
148d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
149d4c9320412177895f598a93d73a0e654db27c351Thomas HellerL1:
1502a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	/* ... Load all the FP registers.  */
151d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	bf	6,L2	/* No floats to load.  */
1522a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lfd	f1, -SAVE_REGS_SIZE-(13*FPR_SIZE)(r28)
1532a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lfd	f2, -SAVE_REGS_SIZE-(12*FPR_SIZE)(r28)
1542a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lfd	f3, -SAVE_REGS_SIZE-(11*FPR_SIZE)(r28)
1552a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lfd	f4, -SAVE_REGS_SIZE-(10*FPR_SIZE)(r28)
156d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	nop
1572a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lfd	f5, -SAVE_REGS_SIZE-( 9*FPR_SIZE)(r28)
1582a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lfd	f6, -SAVE_REGS_SIZE-( 8*FPR_SIZE)(r28)
1592a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lfd	f7, -SAVE_REGS_SIZE-( 7*FPR_SIZE)(r28)
1602a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lfd	f8, -SAVE_REGS_SIZE-( 6*FPR_SIZE)(r28)
161d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	nop
1622a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lfd     f9, -SAVE_REGS_SIZE-( 5*FPR_SIZE)(r28)
1632a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lfd     f10,-SAVE_REGS_SIZE-( 4*FPR_SIZE)(r28)
1642a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lfd     f11,-SAVE_REGS_SIZE-( 3*FPR_SIZE)(r28)
1652a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lfd     f12,-SAVE_REGS_SIZE-( 2*FPR_SIZE)(r28)
166d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	nop
1672a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lfd     f13,-SAVE_REGS_SIZE-( 1*FPR_SIZE)(r28)
168d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
169d4c9320412177895f598a93d73a0e654db27c351Thomas HellerL2:
170d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	mr	r12,r29	/* Put the target address in r12 as specified.  */
171d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	mtctr  	r12
172d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	nop
173d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	nop
1742a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
175d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	/* Make the call.  */
176d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	bctrl
177d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
178d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	/* Now, deal with the return value.  */
179d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
1802a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	/* m64 structure returns can occupy the same set of registers as
1812a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	   would be used to pass such a structure as arg0 - so take care
1822a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	   not to step on any possibly hot regs.  */
183d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
1842a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	/* Get the flags.. */
1852a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	mtcrf	0x03,r31 ; we need c6 & cr7 now.
1862a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	; FLAG_RETURNS_NOTHING also covers struct ret-by-ref.
1872a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	bt	30,L(done_return_value)	  ; FLAG_RETURNS_NOTHING
1882a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	bf	27,L(scalar_return_value) ; not FLAG_RETURNS_STRUCT
1892a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
1902a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	/* OK, so we have a struct.  */
1912a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#if defined(__ppc64__)
1922a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	bt	31,L(maybe_return_128) ; FLAG_RETURNS_128BITS, special case
193d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
1942a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	/* OK, we have to map the return back to a mem struct.
1952a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	   We are about to trample the parents param area, so recover the
1962a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	   return type.  r29 is free, since the call is done.  */
1972a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lg	r29,(LINKAGE_SIZE + 6 * GPR_BYTES)(r28)
1982a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
1992a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	sg	r3, (LINKAGE_SIZE                )(r28)
2002a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	sg	r4, (LINKAGE_SIZE +     GPR_BYTES)(r28)
2012a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	sg	r5, (LINKAGE_SIZE + 2 * GPR_BYTES)(r28)
2022a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	sg	r6, (LINKAGE_SIZE + 3 * GPR_BYTES)(r28)
2032a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	nop
2042a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	sg	r7, (LINKAGE_SIZE + 4 * GPR_BYTES)(r28)
2052a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	sg	r8, (LINKAGE_SIZE + 5 * GPR_BYTES)(r28)
2062a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	sg	r9, (LINKAGE_SIZE + 6 * GPR_BYTES)(r28)
2072a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	sg	r10,(LINKAGE_SIZE + 7 * GPR_BYTES)(r28)
2082a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	/* OK, so do the block move - we trust that memcpy will not trample
2092a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	   the fprs...  */
2102a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	mr 	r3,r30 ; dest
2112a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	addi	r4,r28,LINKAGE_SIZE ; source
2122a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	/* The size is a size_t, should be long.  */
2132a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lg	r5,0(r29)
2142a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	/* Figure out small structs */
2152a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	cmpi	0,r5,4
2162a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	bgt	L3	; 1, 2 and 4 bytes have special rules.
2172a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	cmpi	0,r5,3
2182a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	beq	L3	; not 3
2192a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	addi	r4,r4,8
2202a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	subf	r4,r5,r4
2212a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.comL3:
2222a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	bl	_memcpy
2232a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
2242a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	/* ... do we need the FP registers? - recover the flags.. */
2252a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	mtcrf	0x03,r31 ; we need c6 & cr7 now.
2262a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	bf	29,L(done_return_value)	/* No floats in the struct.  */
2272a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	stfd	f1, -SAVE_REGS_SIZE-(13*FPR_SIZE)(r28)
2282a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	stfd	f2, -SAVE_REGS_SIZE-(12*FPR_SIZE)(r28)
2292a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	stfd	f3, -SAVE_REGS_SIZE-(11*FPR_SIZE)(r28)
2302a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	stfd	f4, -SAVE_REGS_SIZE-(10*FPR_SIZE)(r28)
2312a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	nop
2322a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	stfd	f5, -SAVE_REGS_SIZE-( 9*FPR_SIZE)(r28)
2332a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	stfd	f6, -SAVE_REGS_SIZE-( 8*FPR_SIZE)(r28)
2342a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	stfd	f7, -SAVE_REGS_SIZE-( 7*FPR_SIZE)(r28)
2352a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	stfd	f8, -SAVE_REGS_SIZE-( 6*FPR_SIZE)(r28)
2362a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	nop
2372a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	stfd	f9, -SAVE_REGS_SIZE-( 5*FPR_SIZE)(r28)
2382a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	stfd	f10,-SAVE_REGS_SIZE-( 4*FPR_SIZE)(r28)
2392a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	stfd	f11,-SAVE_REGS_SIZE-( 3*FPR_SIZE)(r28)
2402a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	stfd	f12,-SAVE_REGS_SIZE-( 2*FPR_SIZE)(r28)
2412a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	nop
2422a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	stfd	f13,-SAVE_REGS_SIZE-( 1*FPR_SIZE)(r28)
2432a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
2442a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	mr	r3,r29	; ffi_type *
2452a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	mr	r4,r30	; dest
2462a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	addi	r5,r28,-SAVE_REGS_SIZE-(13*FPR_SIZE) ; fprs
2472a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	xor	r6,r6,r6
2482a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	sg	r6,(LINKAGE_SIZE + 7 * GPR_BYTES)(r28)
2492a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	addi	r6,r28,(LINKAGE_SIZE + 7 * GPR_BYTES) ; point to a zeroed counter.
2502a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	bl 	_darwin64_struct_floats_to_mem
2512a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
2522a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	b L(done_return_value)
2532a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#else
2542a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	stw	r3,0(r30) ; m32 the only struct return in reg is 4 bytes.
2552a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#endif
2562a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	b L(done_return_value)
257d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
258d4c9320412177895f598a93d73a0e654db27c351Thomas HellerL(fp_return_value):
259d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	/* Do we have long double to store?  */
2602a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	bf	31,L(fd_return_value) ; FLAG_RETURNS_128BITS
261d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	stfd	f1,0(r30)
2622a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	stfd	f2,FPR_SIZE(r30)
263d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	b	L(done_return_value)
264d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
265d4c9320412177895f598a93d73a0e654db27c351Thomas HellerL(fd_return_value):
266d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	/* Do we have double to store?  */
267d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	bf	28,L(float_return_value)
268d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	stfd	f1,0(r30)
269d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	b	L(done_return_value)
270d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
271d4c9320412177895f598a93d73a0e654db27c351Thomas HellerL(float_return_value):
272d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	/* We only have a float to store.  */
273d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	stfs	f1,0(r30)
274d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	b	L(done_return_value)
275d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
2762a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.comL(scalar_return_value):
2772a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	bt	29,L(fp_return_value)	; FLAG_RETURNS_FP
2782a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	; ffi_arg is defined as unsigned long.
2792a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	sg	r3,0(r30)		; Save the reg.
2802a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	bf	28,L(done_return_value) ; not FLAG_RETURNS_64BITS
2812a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
2822a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#if defined(__ppc64__)
2832a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.comL(maybe_return_128):
2842a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	std	r3,0(r30)
2852a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	bf	31,L(done_return_value) ; not FLAG_RETURNS_128BITS
2862a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	std	r4,8(r30)
2872a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#else
2882a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	stw	r4,4(r30)
2892a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#endif
2902a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
2912a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	/* Fall through.  */
2922a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	/* We want this at the end to simplify eh epilog computation.  */
2932a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
2942a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.comL(done_return_value):
2952a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	/* Restore the registers we used and return.  */
2962a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lg	r29,SAVED_LR_OFFSET(r28)
2972a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	; epilog
2982a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lg	r31,-(1 * GPR_BYTES)(r28)
2992a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	mtlr	r29
3002a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lg	r30,-(2 * GPR_BYTES)(r28)
3012a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lg	r29,-(3 * GPR_BYTES)(r28)
3022a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lg	r28,-(4 * GPR_BYTES)(r28)
3032a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	lg	r1,0(r1)
3042a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	blr
305d4c9320412177895f598a93d73a0e654db27c351Thomas HellerLFE1:
3062a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	.align	1
307d4c9320412177895f598a93d73a0e654db27c351Thomas Heller/* END(_ffi_call_DARWIN)  */
308d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
309d4c9320412177895f598a93d73a0e654db27c351Thomas Heller/* Provide a null definition of _ffi_call_AIX.  */
3102a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	.text
3112a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	.globl _ffi_call_AIX
312d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.align 2
313d4c9320412177895f598a93d73a0e654db27c351Thomas Heller_ffi_call_AIX:
314d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	blr
315d4c9320412177895f598a93d73a0e654db27c351Thomas Heller/* END(_ffi_call_AIX)  */
316d4c9320412177895f598a93d73a0e654db27c351Thomas Heller
3172a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com/* EH stuff.  */
3182a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
3192a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com#define EH_DATA_ALIGN_FACT MODE_CHOICE(0x7c,0x78)
3202a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
3212a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
322d4c9320412177895f598a93d73a0e654db27c351Thomas HellerEH_frame1:
323d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.set	L$set$0,LECIE1-LSCIE1
324d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.long	L$set$0	; Length of Common Information Entry
325d4c9320412177895f598a93d73a0e654db27c351Thomas HellerLSCIE1:
326d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.long	0x0	; CIE Identifier Tag
327d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x1	; CIE Version
328d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.ascii	"zR\0"	; CIE Augmentation
329d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x1	; uleb128 0x1; CIE Code Alignment Factor
3302a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	.byte	EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor
331d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x41	; CIE RA Column
332d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x1	; uleb128 0x1; Augmentation size
333736a9133219ec75524d90a976d2e35c76d544b6edoko@ubuntu.com	.byte	0x10	; FDE Encoding (pcrel)
334d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0xc	; DW_CFA_def_cfa
335d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x1	; uleb128 0x1
336d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x0	; uleb128 0x0
337d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.align	LOG2_GPR_BYTES
338d4c9320412177895f598a93d73a0e654db27c351Thomas HellerLECIE1:
3392a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
3402a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	.globl _ffi_call_DARWIN.eh
341d4c9320412177895f598a93d73a0e654db27c351Thomas Heller_ffi_call_DARWIN.eh:
342d4c9320412177895f598a93d73a0e654db27c351Thomas HellerLSFDE1:
343d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.set	L$set$1,LEFDE1-LASFDE1
344d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.long	L$set$1	; FDE Length
345d4c9320412177895f598a93d73a0e654db27c351Thomas HellerLASFDE1:
346d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.long	LASFDE1-EH_frame1 ; FDE CIE offset
347736a9133219ec75524d90a976d2e35c76d544b6edoko@ubuntu.com	.g_long	Lstartcode-.	; FDE initial location
3482a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	.set	L$set$3,LFE1-Lstartcode
349d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.g_long	L$set$3	; FDE address range
350d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte   0x0     ; uleb128 0x0; Augmentation size
351d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x4	; DW_CFA_advance_loc4
3522a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	.set	L$set$4,LCFI0-Lstartcode
353d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.long	L$set$4
354d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0xd	; DW_CFA_def_cfa_register
355d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x08	; uleb128 0x08
356d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x4	; DW_CFA_advance_loc4
357d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.set	L$set$5,LCFI1-LCFI0
358d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.long	L$set$5
359d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte   0x11    ; DW_CFA_offset_extended_sf
360d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x41	; uleb128 0x41
361d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte   0x7e    ; sleb128 -2
362d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x9f	; DW_CFA_offset, column 0x1f
363d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x1	; uleb128 0x1
364d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x9e	; DW_CFA_offset, column 0x1e
365d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x2	; uleb128 0x2
366d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x9d	; DW_CFA_offset, column 0x1d
367d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x3	; uleb128 0x3
368d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x9c	; DW_CFA_offset, column 0x1c
369d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x4	; uleb128 0x4
370d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x4	; DW_CFA_advance_loc4
371d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.set	L$set$6,LCFI2-LCFI1
372d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.long	L$set$6
373d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0xd	; DW_CFA_def_cfa_register
374d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.byte	0x1c	; uleb128 0x1c
375d4c9320412177895f598a93d73a0e654db27c351Thomas Heller	.align LOG2_GPR_BYTES
376d4c9320412177895f598a93d73a0e654db27c351Thomas HellerLEFDE1:
3772a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com	.align 1
3782a918768f1825d4a1f1e5f11674614c74176aa5ddoko@ubuntu.com
379