xref: /aosp_15_r20/external/libffi/src/powerpc/ffi_darwin.c (revision 1fd5a2e1d639cd1ddf29dd0c484c123bbd850c21)
1*1fd5a2e1SPrashanth Swaminathan /* -----------------------------------------------------------------------
2*1fd5a2e1SPrashanth Swaminathan    ffi_darwin.c
3*1fd5a2e1SPrashanth Swaminathan 
4*1fd5a2e1SPrashanth Swaminathan    Copyright (C) 1998 Geoffrey Keating
5*1fd5a2e1SPrashanth Swaminathan    Copyright (C) 2001 John Hornkvist
6*1fd5a2e1SPrashanth Swaminathan    Copyright (C) 2002, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
7*1fd5a2e1SPrashanth Swaminathan 
8*1fd5a2e1SPrashanth Swaminathan    FFI support for Darwin and AIX.
9*1fd5a2e1SPrashanth Swaminathan 
10*1fd5a2e1SPrashanth Swaminathan    Permission is hereby granted, free of charge, to any person obtaining
11*1fd5a2e1SPrashanth Swaminathan    a copy of this software and associated documentation files (the
12*1fd5a2e1SPrashanth Swaminathan    ``Software''), to deal in the Software without restriction, including
13*1fd5a2e1SPrashanth Swaminathan    without limitation the rights to use, copy, modify, merge, publish,
14*1fd5a2e1SPrashanth Swaminathan    distribute, sublicense, and/or sell copies of the Software, and to
15*1fd5a2e1SPrashanth Swaminathan    permit persons to whom the Software is furnished to do so, subject to
16*1fd5a2e1SPrashanth Swaminathan    the following conditions:
17*1fd5a2e1SPrashanth Swaminathan 
18*1fd5a2e1SPrashanth Swaminathan    The above copyright notice and this permission notice shall be included
19*1fd5a2e1SPrashanth Swaminathan    in all copies or substantial portions of the Software.
20*1fd5a2e1SPrashanth Swaminathan 
21*1fd5a2e1SPrashanth Swaminathan    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
22*1fd5a2e1SPrashanth Swaminathan    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23*1fd5a2e1SPrashanth Swaminathan    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24*1fd5a2e1SPrashanth Swaminathan    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
25*1fd5a2e1SPrashanth Swaminathan    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26*1fd5a2e1SPrashanth Swaminathan    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27*1fd5a2e1SPrashanth Swaminathan    OTHER DEALINGS IN THE SOFTWARE.
28*1fd5a2e1SPrashanth Swaminathan    ----------------------------------------------------------------------- */
29*1fd5a2e1SPrashanth Swaminathan 
30*1fd5a2e1SPrashanth Swaminathan #include <ffi.h>
31*1fd5a2e1SPrashanth Swaminathan #include <ffi_common.h>
32*1fd5a2e1SPrashanth Swaminathan 
33*1fd5a2e1SPrashanth Swaminathan #include <stdlib.h>
34*1fd5a2e1SPrashanth Swaminathan 
35*1fd5a2e1SPrashanth Swaminathan extern void ffi_closure_ASM (void);
36*1fd5a2e1SPrashanth Swaminathan extern void ffi_go_closure_ASM (void);
37*1fd5a2e1SPrashanth Swaminathan 
38*1fd5a2e1SPrashanth Swaminathan enum {
39*1fd5a2e1SPrashanth Swaminathan   /* The assembly depends on these exact flags.
40*1fd5a2e1SPrashanth Swaminathan      For Darwin64 (when FLAG_RETURNS_STRUCT is set):
41*1fd5a2e1SPrashanth Swaminathan        FLAG_RETURNS_FP indicates that the structure embeds FP data.
42*1fd5a2e1SPrashanth Swaminathan        FLAG_RETURNS_128BITS signals a special struct size that is not
43*1fd5a2e1SPrashanth Swaminathan        expanded for float content.  */
44*1fd5a2e1SPrashanth Swaminathan   FLAG_RETURNS_128BITS	= 1 << (31-31), /* These go in cr7  */
45*1fd5a2e1SPrashanth Swaminathan   FLAG_RETURNS_NOTHING	= 1 << (31-30),
46*1fd5a2e1SPrashanth Swaminathan   FLAG_RETURNS_FP	= 1 << (31-29),
47*1fd5a2e1SPrashanth Swaminathan   FLAG_RETURNS_64BITS	= 1 << (31-28),
48*1fd5a2e1SPrashanth Swaminathan 
49*1fd5a2e1SPrashanth Swaminathan   FLAG_RETURNS_STRUCT	= 1 << (31-27), /* This goes in cr6  */
50*1fd5a2e1SPrashanth Swaminathan 
51*1fd5a2e1SPrashanth Swaminathan   FLAG_ARG_NEEDS_COPY   = 1 << (31- 7),
52*1fd5a2e1SPrashanth Swaminathan   FLAG_FP_ARGUMENTS     = 1 << (31- 6), /* cr1.eq; specified by ABI  */
53*1fd5a2e1SPrashanth Swaminathan   FLAG_4_GPR_ARGUMENTS  = 1 << (31- 5),
54*1fd5a2e1SPrashanth Swaminathan   FLAG_RETVAL_REFERENCE = 1 << (31- 4)
55*1fd5a2e1SPrashanth Swaminathan };
56*1fd5a2e1SPrashanth Swaminathan 
57*1fd5a2e1SPrashanth Swaminathan /* About the DARWIN ABI.  */
58*1fd5a2e1SPrashanth Swaminathan enum {
59*1fd5a2e1SPrashanth Swaminathan   NUM_GPR_ARG_REGISTERS = 8,
60*1fd5a2e1SPrashanth Swaminathan   NUM_FPR_ARG_REGISTERS = 13,
61*1fd5a2e1SPrashanth Swaminathan   LINKAGE_AREA_GPRS = 6
62*1fd5a2e1SPrashanth Swaminathan };
63*1fd5a2e1SPrashanth Swaminathan 
64*1fd5a2e1SPrashanth Swaminathan enum { ASM_NEEDS_REGISTERS = 4 }; /* r28-r31 */
65*1fd5a2e1SPrashanth Swaminathan 
66*1fd5a2e1SPrashanth Swaminathan /* ffi_prep_args is called by the assembly routine once stack space
67*1fd5a2e1SPrashanth Swaminathan    has been allocated for the function's arguments.
68*1fd5a2e1SPrashanth Swaminathan 
69*1fd5a2e1SPrashanth Swaminathan    m32/m64
70*1fd5a2e1SPrashanth Swaminathan 
71*1fd5a2e1SPrashanth Swaminathan    The stack layout we want looks like this:
72*1fd5a2e1SPrashanth Swaminathan 
73*1fd5a2e1SPrashanth Swaminathan    |   Return address from ffi_call_DARWIN      |	higher addresses
74*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------|
75*1fd5a2e1SPrashanth Swaminathan    |   Previous backchain pointer	4/8	|	stack pointer here
76*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------|<+ <<<	on entry to
77*1fd5a2e1SPrashanth Swaminathan    |   ASM_NEEDS_REGISTERS=r28-r31   4*(4/8)	| |	ffi_call_DARWIN
78*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |
79*1fd5a2e1SPrashanth Swaminathan    |   When we have any FP activity... the	| |
80*1fd5a2e1SPrashanth Swaminathan    |   FPRs occupy NUM_FPR_ARG_REGISTERS slots	| |
81*1fd5a2e1SPrashanth Swaminathan    |   here fp13 .. fp1 from high to low addr.	| |
82*1fd5a2e1SPrashanth Swaminathan    ~						~ ~
83*1fd5a2e1SPrashanth Swaminathan    |   Parameters      (at least 8*4/8=32/64)	| | NUM_GPR_ARG_REGISTERS
84*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |
85*1fd5a2e1SPrashanth Swaminathan    |   TOC=R2 (AIX) Reserved (Darwin)   4/8	| |
86*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |	stack	|
87*1fd5a2e1SPrashanth Swaminathan    |   Reserved                       2*4/8	| |	grows	|
88*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |	down	V
89*1fd5a2e1SPrashanth Swaminathan    |   Space for callee's LR		4/8	| |
90*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |	lower addresses
91*1fd5a2e1SPrashanth Swaminathan    |   Saved CR [low word for m64]      4/8	| |
92*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |     stack pointer here
93*1fd5a2e1SPrashanth Swaminathan    |   Current backchain pointer	4/8	|-/	during
94*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------|   <<<	ffi_call_DARWIN
95*1fd5a2e1SPrashanth Swaminathan 
96*1fd5a2e1SPrashanth Swaminathan    */
97*1fd5a2e1SPrashanth Swaminathan 
98*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
99*1fd5a2e1SPrashanth Swaminathan static void
100*1fd5a2e1SPrashanth Swaminathan darwin64_pass_struct_by_value
101*1fd5a2e1SPrashanth Swaminathan   (ffi_type *, char *, unsigned, unsigned *, double **, unsigned long **);
102*1fd5a2e1SPrashanth Swaminathan #endif
103*1fd5a2e1SPrashanth Swaminathan 
104*1fd5a2e1SPrashanth Swaminathan /* This depends on GPR_SIZE = sizeof (unsigned long) */
105*1fd5a2e1SPrashanth Swaminathan 
106*1fd5a2e1SPrashanth Swaminathan void
ffi_prep_args(extended_cif * ecif,unsigned long * const stack)107*1fd5a2e1SPrashanth Swaminathan ffi_prep_args (extended_cif *ecif, unsigned long *const stack)
108*1fd5a2e1SPrashanth Swaminathan {
109*1fd5a2e1SPrashanth Swaminathan   const unsigned bytes = ecif->cif->bytes;
110*1fd5a2e1SPrashanth Swaminathan   const unsigned flags = ecif->cif->flags;
111*1fd5a2e1SPrashanth Swaminathan   const unsigned nargs = ecif->cif->nargs;
112*1fd5a2e1SPrashanth Swaminathan #if !defined(POWERPC_DARWIN64)
113*1fd5a2e1SPrashanth Swaminathan   const ffi_abi abi = ecif->cif->abi;
114*1fd5a2e1SPrashanth Swaminathan #endif
115*1fd5a2e1SPrashanth Swaminathan 
116*1fd5a2e1SPrashanth Swaminathan   /* 'stacktop' points at the previous backchain pointer.  */
117*1fd5a2e1SPrashanth Swaminathan   unsigned long *const stacktop = stack + (bytes / sizeof(unsigned long));
118*1fd5a2e1SPrashanth Swaminathan 
119*1fd5a2e1SPrashanth Swaminathan   /* 'fpr_base' points at the space for fpr1, and grows upwards as
120*1fd5a2e1SPrashanth Swaminathan      we use FPR registers.  */
121*1fd5a2e1SPrashanth Swaminathan   double *fpr_base = (double *) (stacktop - ASM_NEEDS_REGISTERS) - NUM_FPR_ARG_REGISTERS;
122*1fd5a2e1SPrashanth Swaminathan   int gp_count = 0, fparg_count = 0;
123*1fd5a2e1SPrashanth Swaminathan 
124*1fd5a2e1SPrashanth Swaminathan   /* 'next_arg' grows up as we put parameters in it.  */
125*1fd5a2e1SPrashanth Swaminathan   unsigned long *next_arg = stack + LINKAGE_AREA_GPRS; /* 6 reserved positions.  */
126*1fd5a2e1SPrashanth Swaminathan 
127*1fd5a2e1SPrashanth Swaminathan   int i;
128*1fd5a2e1SPrashanth Swaminathan   double double_tmp;
129*1fd5a2e1SPrashanth Swaminathan   void **p_argv = ecif->avalue;
130*1fd5a2e1SPrashanth Swaminathan   unsigned long gprvalue;
131*1fd5a2e1SPrashanth Swaminathan   ffi_type** ptr = ecif->cif->arg_types;
132*1fd5a2e1SPrashanth Swaminathan #if !defined(POWERPC_DARWIN64)
133*1fd5a2e1SPrashanth Swaminathan   char *dest_cpy;
134*1fd5a2e1SPrashanth Swaminathan #endif
135*1fd5a2e1SPrashanth Swaminathan   unsigned size_al = 0;
136*1fd5a2e1SPrashanth Swaminathan 
137*1fd5a2e1SPrashanth Swaminathan   /* Check that everything starts aligned properly.  */
138*1fd5a2e1SPrashanth Swaminathan   FFI_ASSERT(((unsigned) (char *) stack & 0xF) == 0);
139*1fd5a2e1SPrashanth Swaminathan   FFI_ASSERT(((unsigned) (char *) stacktop & 0xF) == 0);
140*1fd5a2e1SPrashanth Swaminathan   FFI_ASSERT((bytes & 0xF) == 0);
141*1fd5a2e1SPrashanth Swaminathan 
142*1fd5a2e1SPrashanth Swaminathan   /* Deal with return values that are actually pass-by-reference.
143*1fd5a2e1SPrashanth Swaminathan      Rule:
144*1fd5a2e1SPrashanth Swaminathan      Return values are referenced by r3, so r4 is the first parameter.  */
145*1fd5a2e1SPrashanth Swaminathan 
146*1fd5a2e1SPrashanth Swaminathan   if (flags & FLAG_RETVAL_REFERENCE)
147*1fd5a2e1SPrashanth Swaminathan     *next_arg++ = (unsigned long) (char *) ecif->rvalue;
148*1fd5a2e1SPrashanth Swaminathan 
149*1fd5a2e1SPrashanth Swaminathan   /* Now for the arguments.  */
150*1fd5a2e1SPrashanth Swaminathan   for (i = nargs; i > 0; i--, ptr++, p_argv++)
151*1fd5a2e1SPrashanth Swaminathan     {
152*1fd5a2e1SPrashanth Swaminathan       switch ((*ptr)->type)
153*1fd5a2e1SPrashanth Swaminathan 	{
154*1fd5a2e1SPrashanth Swaminathan 	/* If a floating-point parameter appears before all of the general-
155*1fd5a2e1SPrashanth Swaminathan 	   purpose registers are filled, the corresponding GPRs that match
156*1fd5a2e1SPrashanth Swaminathan 	   the size of the floating-point parameter are skipped.  */
157*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_FLOAT:
158*1fd5a2e1SPrashanth Swaminathan 	  double_tmp = *(float *) *p_argv;
159*1fd5a2e1SPrashanth Swaminathan 	  if (fparg_count < NUM_FPR_ARG_REGISTERS)
160*1fd5a2e1SPrashanth Swaminathan 	    *fpr_base++ = double_tmp;
161*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN)
162*1fd5a2e1SPrashanth Swaminathan 	  *(float *)next_arg = *(float *) *p_argv;
163*1fd5a2e1SPrashanth Swaminathan #else
164*1fd5a2e1SPrashanth Swaminathan 	  *(double *)next_arg = double_tmp;
165*1fd5a2e1SPrashanth Swaminathan #endif
166*1fd5a2e1SPrashanth Swaminathan 	  next_arg++;
167*1fd5a2e1SPrashanth Swaminathan 	  gp_count++;
168*1fd5a2e1SPrashanth Swaminathan 	  fparg_count++;
169*1fd5a2e1SPrashanth Swaminathan 	  FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
170*1fd5a2e1SPrashanth Swaminathan 	  break;
171*1fd5a2e1SPrashanth Swaminathan 
172*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_DOUBLE:
173*1fd5a2e1SPrashanth Swaminathan 	  double_tmp = *(double *) *p_argv;
174*1fd5a2e1SPrashanth Swaminathan 	  if (fparg_count < NUM_FPR_ARG_REGISTERS)
175*1fd5a2e1SPrashanth Swaminathan 	    *fpr_base++ = double_tmp;
176*1fd5a2e1SPrashanth Swaminathan 	  *(double *)next_arg = double_tmp;
177*1fd5a2e1SPrashanth Swaminathan #ifdef POWERPC64
178*1fd5a2e1SPrashanth Swaminathan 	  next_arg++;
179*1fd5a2e1SPrashanth Swaminathan 	  gp_count++;
180*1fd5a2e1SPrashanth Swaminathan #else
181*1fd5a2e1SPrashanth Swaminathan 	  next_arg += 2;
182*1fd5a2e1SPrashanth Swaminathan 	  gp_count += 2;
183*1fd5a2e1SPrashanth Swaminathan #endif
184*1fd5a2e1SPrashanth Swaminathan 	  fparg_count++;
185*1fd5a2e1SPrashanth Swaminathan 	  FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
186*1fd5a2e1SPrashanth Swaminathan 	  break;
187*1fd5a2e1SPrashanth Swaminathan 
188*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
189*1fd5a2e1SPrashanth Swaminathan 
190*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_LONGDOUBLE:
191*1fd5a2e1SPrashanth Swaminathan #  if defined(POWERPC64) && !defined(POWERPC_DARWIN64)
192*1fd5a2e1SPrashanth Swaminathan 	  /* ??? This will exceed the regs count when the value starts at fp13
193*1fd5a2e1SPrashanth Swaminathan 	     and it will not put the extra bit on the stack.  */
194*1fd5a2e1SPrashanth Swaminathan 	  if (fparg_count < NUM_FPR_ARG_REGISTERS)
195*1fd5a2e1SPrashanth Swaminathan 	    *(long double *) fpr_base++ = *(long double *) *p_argv;
196*1fd5a2e1SPrashanth Swaminathan 	  else
197*1fd5a2e1SPrashanth Swaminathan 	    *(long double *) next_arg = *(long double *) *p_argv;
198*1fd5a2e1SPrashanth Swaminathan 	  next_arg += 2;
199*1fd5a2e1SPrashanth Swaminathan 	  fparg_count += 2;
200*1fd5a2e1SPrashanth Swaminathan #  else
201*1fd5a2e1SPrashanth Swaminathan 	  double_tmp = ((double *) *p_argv)[0];
202*1fd5a2e1SPrashanth Swaminathan 	  if (fparg_count < NUM_FPR_ARG_REGISTERS)
203*1fd5a2e1SPrashanth Swaminathan 	    *fpr_base++ = double_tmp;
204*1fd5a2e1SPrashanth Swaminathan 	  *(double *) next_arg = double_tmp;
205*1fd5a2e1SPrashanth Swaminathan #    if defined(POWERPC_DARWIN64)
206*1fd5a2e1SPrashanth Swaminathan 	  next_arg++;
207*1fd5a2e1SPrashanth Swaminathan 	  gp_count++;
208*1fd5a2e1SPrashanth Swaminathan #    else
209*1fd5a2e1SPrashanth Swaminathan 	  next_arg += 2;
210*1fd5a2e1SPrashanth Swaminathan 	  gp_count += 2;
211*1fd5a2e1SPrashanth Swaminathan #    endif
212*1fd5a2e1SPrashanth Swaminathan 	  fparg_count++;
213*1fd5a2e1SPrashanth Swaminathan 	  double_tmp = ((double *) *p_argv)[1];
214*1fd5a2e1SPrashanth Swaminathan 	  if (fparg_count < NUM_FPR_ARG_REGISTERS)
215*1fd5a2e1SPrashanth Swaminathan 	    *fpr_base++ = double_tmp;
216*1fd5a2e1SPrashanth Swaminathan 	  *(double *) next_arg = double_tmp;
217*1fd5a2e1SPrashanth Swaminathan #    if defined(POWERPC_DARWIN64)
218*1fd5a2e1SPrashanth Swaminathan 	  next_arg++;
219*1fd5a2e1SPrashanth Swaminathan 	  gp_count++;
220*1fd5a2e1SPrashanth Swaminathan #    else
221*1fd5a2e1SPrashanth Swaminathan 	  next_arg += 2;
222*1fd5a2e1SPrashanth Swaminathan 	  gp_count += 2;
223*1fd5a2e1SPrashanth Swaminathan #    endif
224*1fd5a2e1SPrashanth Swaminathan 	  fparg_count++;
225*1fd5a2e1SPrashanth Swaminathan #  endif
226*1fd5a2e1SPrashanth Swaminathan 	  FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
227*1fd5a2e1SPrashanth Swaminathan 	  break;
228*1fd5a2e1SPrashanth Swaminathan #endif
229*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT64:
230*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT64:
231*1fd5a2e1SPrashanth Swaminathan #ifdef POWERPC64
232*1fd5a2e1SPrashanth Swaminathan 	  gprvalue = *(long long *) *p_argv;
233*1fd5a2e1SPrashanth Swaminathan 	  goto putgpr;
234*1fd5a2e1SPrashanth Swaminathan #else
235*1fd5a2e1SPrashanth Swaminathan 	  *(long long *) next_arg = *(long long *) *p_argv;
236*1fd5a2e1SPrashanth Swaminathan 	  next_arg += 2;
237*1fd5a2e1SPrashanth Swaminathan 	  gp_count += 2;
238*1fd5a2e1SPrashanth Swaminathan #endif
239*1fd5a2e1SPrashanth Swaminathan 	  break;
240*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_POINTER:
241*1fd5a2e1SPrashanth Swaminathan 	  gprvalue = *(unsigned long *) *p_argv;
242*1fd5a2e1SPrashanth Swaminathan 	  goto putgpr;
243*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT8:
244*1fd5a2e1SPrashanth Swaminathan 	  gprvalue = *(unsigned char *) *p_argv;
245*1fd5a2e1SPrashanth Swaminathan 	  goto putgpr;
246*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT8:
247*1fd5a2e1SPrashanth Swaminathan 	  gprvalue = *(signed char *) *p_argv;
248*1fd5a2e1SPrashanth Swaminathan 	  goto putgpr;
249*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT16:
250*1fd5a2e1SPrashanth Swaminathan 	  gprvalue = *(unsigned short *) *p_argv;
251*1fd5a2e1SPrashanth Swaminathan 	  goto putgpr;
252*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT16:
253*1fd5a2e1SPrashanth Swaminathan 	  gprvalue = *(signed short *) *p_argv;
254*1fd5a2e1SPrashanth Swaminathan 	  goto putgpr;
255*1fd5a2e1SPrashanth Swaminathan 
256*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_STRUCT:
257*1fd5a2e1SPrashanth Swaminathan 	  size_al = (*ptr)->size;
258*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
259*1fd5a2e1SPrashanth Swaminathan 	  next_arg = (unsigned long *)FFI_ALIGN((char *)next_arg, (*ptr)->alignment);
260*1fd5a2e1SPrashanth Swaminathan 	  darwin64_pass_struct_by_value (*ptr, (char *) *p_argv,
261*1fd5a2e1SPrashanth Swaminathan 					 (unsigned) size_al,
262*1fd5a2e1SPrashanth Swaminathan 					 (unsigned int *) &fparg_count,
263*1fd5a2e1SPrashanth Swaminathan 					 &fpr_base, &next_arg);
264*1fd5a2e1SPrashanth Swaminathan #else
265*1fd5a2e1SPrashanth Swaminathan 	  dest_cpy = (char *) next_arg;
266*1fd5a2e1SPrashanth Swaminathan 
267*1fd5a2e1SPrashanth Swaminathan 	  /* If the first member of the struct is a double, then include enough
268*1fd5a2e1SPrashanth Swaminathan 	     padding in the struct size to align it to double-word.  */
269*1fd5a2e1SPrashanth Swaminathan 	  if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE)
270*1fd5a2e1SPrashanth Swaminathan 	    size_al = FFI_ALIGN((*ptr)->size, 8);
271*1fd5a2e1SPrashanth Swaminathan 
272*1fd5a2e1SPrashanth Swaminathan #  if defined(POWERPC64)
273*1fd5a2e1SPrashanth Swaminathan 	  FFI_ASSERT (abi != FFI_DARWIN);
274*1fd5a2e1SPrashanth Swaminathan 	  memcpy ((char *) dest_cpy, (char *) *p_argv, size_al);
275*1fd5a2e1SPrashanth Swaminathan 	  next_arg += (size_al + 7) / 8;
276*1fd5a2e1SPrashanth Swaminathan #  else
277*1fd5a2e1SPrashanth Swaminathan 	  /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
278*1fd5a2e1SPrashanth Swaminathan 	     SI 4 bytes) are aligned as if they were those modes.
279*1fd5a2e1SPrashanth Swaminathan 	     Structures with 3 byte in size are padded upwards.  */
280*1fd5a2e1SPrashanth Swaminathan 	  if (size_al < 3 && abi == FFI_DARWIN)
281*1fd5a2e1SPrashanth Swaminathan 	    dest_cpy += 4 - size_al;
282*1fd5a2e1SPrashanth Swaminathan 
283*1fd5a2e1SPrashanth Swaminathan 	  memcpy((char *) dest_cpy, (char *) *p_argv, size_al);
284*1fd5a2e1SPrashanth Swaminathan 	  next_arg += (size_al + 3) / 4;
285*1fd5a2e1SPrashanth Swaminathan #  endif
286*1fd5a2e1SPrashanth Swaminathan #endif
287*1fd5a2e1SPrashanth Swaminathan 	  break;
288*1fd5a2e1SPrashanth Swaminathan 
289*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_INT:
290*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT32:
291*1fd5a2e1SPrashanth Swaminathan 	  gprvalue = *(signed int *) *p_argv;
292*1fd5a2e1SPrashanth Swaminathan 	  goto putgpr;
293*1fd5a2e1SPrashanth Swaminathan 
294*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT32:
295*1fd5a2e1SPrashanth Swaminathan 	  gprvalue = *(unsigned int *) *p_argv;
296*1fd5a2e1SPrashanth Swaminathan 	putgpr:
297*1fd5a2e1SPrashanth Swaminathan 	  *next_arg++ = gprvalue;
298*1fd5a2e1SPrashanth Swaminathan 	  gp_count++;
299*1fd5a2e1SPrashanth Swaminathan 	  break;
300*1fd5a2e1SPrashanth Swaminathan 	default:
301*1fd5a2e1SPrashanth Swaminathan 	  break;
302*1fd5a2e1SPrashanth Swaminathan 	}
303*1fd5a2e1SPrashanth Swaminathan     }
304*1fd5a2e1SPrashanth Swaminathan 
305*1fd5a2e1SPrashanth Swaminathan   /* Check that we didn't overrun the stack...  */
306*1fd5a2e1SPrashanth Swaminathan   /* FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
307*1fd5a2e1SPrashanth Swaminathan      FFI_ASSERT((unsigned *)fpr_base
308*1fd5a2e1SPrashanth Swaminathan      	     <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
309*1fd5a2e1SPrashanth Swaminathan      FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);  */
310*1fd5a2e1SPrashanth Swaminathan }
311*1fd5a2e1SPrashanth Swaminathan 
312*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
313*1fd5a2e1SPrashanth Swaminathan 
314*1fd5a2e1SPrashanth Swaminathan /* See if we can put some of the struct into fprs.
315*1fd5a2e1SPrashanth Swaminathan    This should not be called for structures of size 16 bytes, since these are not
316*1fd5a2e1SPrashanth Swaminathan    broken out this way.  */
317*1fd5a2e1SPrashanth Swaminathan static void
darwin64_scan_struct_for_floats(ffi_type * s,unsigned * nfpr)318*1fd5a2e1SPrashanth Swaminathan darwin64_scan_struct_for_floats (ffi_type *s, unsigned *nfpr)
319*1fd5a2e1SPrashanth Swaminathan {
320*1fd5a2e1SPrashanth Swaminathan   int i;
321*1fd5a2e1SPrashanth Swaminathan 
322*1fd5a2e1SPrashanth Swaminathan   FFI_ASSERT (s->type == FFI_TYPE_STRUCT)
323*1fd5a2e1SPrashanth Swaminathan 
324*1fd5a2e1SPrashanth Swaminathan   for (i = 0; s->elements[i] != NULL; i++)
325*1fd5a2e1SPrashanth Swaminathan     {
326*1fd5a2e1SPrashanth Swaminathan       ffi_type *p = s->elements[i];
327*1fd5a2e1SPrashanth Swaminathan       switch (p->type)
328*1fd5a2e1SPrashanth Swaminathan 	{
329*1fd5a2e1SPrashanth Swaminathan 	  case FFI_TYPE_STRUCT:
330*1fd5a2e1SPrashanth Swaminathan 	    darwin64_scan_struct_for_floats (p, nfpr);
331*1fd5a2e1SPrashanth Swaminathan 	    break;
332*1fd5a2e1SPrashanth Swaminathan 	  case FFI_TYPE_LONGDOUBLE:
333*1fd5a2e1SPrashanth Swaminathan 	    (*nfpr) += 2;
334*1fd5a2e1SPrashanth Swaminathan 	    break;
335*1fd5a2e1SPrashanth Swaminathan 	  case FFI_TYPE_DOUBLE:
336*1fd5a2e1SPrashanth Swaminathan 	  case FFI_TYPE_FLOAT:
337*1fd5a2e1SPrashanth Swaminathan 	    (*nfpr) += 1;
338*1fd5a2e1SPrashanth Swaminathan 	    break;
339*1fd5a2e1SPrashanth Swaminathan 	  default:
340*1fd5a2e1SPrashanth Swaminathan 	    break;
341*1fd5a2e1SPrashanth Swaminathan 	}
342*1fd5a2e1SPrashanth Swaminathan     }
343*1fd5a2e1SPrashanth Swaminathan }
344*1fd5a2e1SPrashanth Swaminathan 
345*1fd5a2e1SPrashanth Swaminathan static int
darwin64_struct_size_exceeds_gprs_p(ffi_type * s,char * src,unsigned * nfpr)346*1fd5a2e1SPrashanth Swaminathan darwin64_struct_size_exceeds_gprs_p (ffi_type *s, char *src, unsigned *nfpr)
347*1fd5a2e1SPrashanth Swaminathan {
348*1fd5a2e1SPrashanth Swaminathan   unsigned struct_offset=0, i;
349*1fd5a2e1SPrashanth Swaminathan 
350*1fd5a2e1SPrashanth Swaminathan   for (i = 0; s->elements[i] != NULL; i++)
351*1fd5a2e1SPrashanth Swaminathan     {
352*1fd5a2e1SPrashanth Swaminathan       char *item_base;
353*1fd5a2e1SPrashanth Swaminathan       ffi_type *p = s->elements[i];
354*1fd5a2e1SPrashanth Swaminathan       /* Find the start of this item (0 for the first one).  */
355*1fd5a2e1SPrashanth Swaminathan       if (i > 0)
356*1fd5a2e1SPrashanth Swaminathan         struct_offset = FFI_ALIGN(struct_offset, p->alignment);
357*1fd5a2e1SPrashanth Swaminathan 
358*1fd5a2e1SPrashanth Swaminathan       item_base = src + struct_offset;
359*1fd5a2e1SPrashanth Swaminathan 
360*1fd5a2e1SPrashanth Swaminathan       switch (p->type)
361*1fd5a2e1SPrashanth Swaminathan 	{
362*1fd5a2e1SPrashanth Swaminathan 	  case FFI_TYPE_STRUCT:
363*1fd5a2e1SPrashanth Swaminathan 	    if (darwin64_struct_size_exceeds_gprs_p (p, item_base, nfpr))
364*1fd5a2e1SPrashanth Swaminathan 	      return 1;
365*1fd5a2e1SPrashanth Swaminathan 	    break;
366*1fd5a2e1SPrashanth Swaminathan 	  case FFI_TYPE_LONGDOUBLE:
367*1fd5a2e1SPrashanth Swaminathan 	    if (*nfpr >= NUM_FPR_ARG_REGISTERS)
368*1fd5a2e1SPrashanth Swaminathan 	      return 1;
369*1fd5a2e1SPrashanth Swaminathan 	    (*nfpr) += 1;
370*1fd5a2e1SPrashanth Swaminathan 	    item_base += 8;
371*1fd5a2e1SPrashanth Swaminathan 	  /* FALL THROUGH */
372*1fd5a2e1SPrashanth Swaminathan 	  case FFI_TYPE_DOUBLE:
373*1fd5a2e1SPrashanth Swaminathan 	    if (*nfpr >= NUM_FPR_ARG_REGISTERS)
374*1fd5a2e1SPrashanth Swaminathan 	      return 1;
375*1fd5a2e1SPrashanth Swaminathan 	    (*nfpr) += 1;
376*1fd5a2e1SPrashanth Swaminathan 	    break;
377*1fd5a2e1SPrashanth Swaminathan 	  case FFI_TYPE_FLOAT:
378*1fd5a2e1SPrashanth Swaminathan 	    if (*nfpr >= NUM_FPR_ARG_REGISTERS)
379*1fd5a2e1SPrashanth Swaminathan 	      return 1;
380*1fd5a2e1SPrashanth Swaminathan 	    (*nfpr) += 1;
381*1fd5a2e1SPrashanth Swaminathan 	    break;
382*1fd5a2e1SPrashanth Swaminathan 	  default:
383*1fd5a2e1SPrashanth Swaminathan 	    /* If we try and place any item, that is non-float, once we've
384*1fd5a2e1SPrashanth Swaminathan 	       exceeded the 8 GPR mark, then we can't fit the struct.  */
385*1fd5a2e1SPrashanth Swaminathan 	    if ((unsigned long)item_base >= 8*8)
386*1fd5a2e1SPrashanth Swaminathan 	      return 1;
387*1fd5a2e1SPrashanth Swaminathan 	    break;
388*1fd5a2e1SPrashanth Swaminathan 	}
389*1fd5a2e1SPrashanth Swaminathan       /* now count the size of what we just used.  */
390*1fd5a2e1SPrashanth Swaminathan       struct_offset += p->size;
391*1fd5a2e1SPrashanth Swaminathan     }
392*1fd5a2e1SPrashanth Swaminathan   return 0;
393*1fd5a2e1SPrashanth Swaminathan }
394*1fd5a2e1SPrashanth Swaminathan 
395*1fd5a2e1SPrashanth Swaminathan /* Can this struct be returned by value?  */
396*1fd5a2e1SPrashanth Swaminathan int
darwin64_struct_ret_by_value_p(ffi_type * s)397*1fd5a2e1SPrashanth Swaminathan darwin64_struct_ret_by_value_p (ffi_type *s)
398*1fd5a2e1SPrashanth Swaminathan {
399*1fd5a2e1SPrashanth Swaminathan   unsigned nfp = 0;
400*1fd5a2e1SPrashanth Swaminathan 
401*1fd5a2e1SPrashanth Swaminathan   FFI_ASSERT (s && s->type == FFI_TYPE_STRUCT);
402*1fd5a2e1SPrashanth Swaminathan 
403*1fd5a2e1SPrashanth Swaminathan   /* The largest structure we can return is 8long + 13 doubles.  */
404*1fd5a2e1SPrashanth Swaminathan   if (s->size > 168)
405*1fd5a2e1SPrashanth Swaminathan     return 0;
406*1fd5a2e1SPrashanth Swaminathan 
407*1fd5a2e1SPrashanth Swaminathan   /* We can't pass more than 13 floats.  */
408*1fd5a2e1SPrashanth Swaminathan   darwin64_scan_struct_for_floats (s, &nfp);
409*1fd5a2e1SPrashanth Swaminathan   if (nfp > 13)
410*1fd5a2e1SPrashanth Swaminathan     return 0;
411*1fd5a2e1SPrashanth Swaminathan 
412*1fd5a2e1SPrashanth Swaminathan   /* If there are not too many floats, and the struct is
413*1fd5a2e1SPrashanth Swaminathan      small enough to accommodate in the GPRs, then it must be OK.  */
414*1fd5a2e1SPrashanth Swaminathan   if (s->size <= 64)
415*1fd5a2e1SPrashanth Swaminathan     return 1;
416*1fd5a2e1SPrashanth Swaminathan 
417*1fd5a2e1SPrashanth Swaminathan   /* Well, we have to look harder.  */
418*1fd5a2e1SPrashanth Swaminathan   nfp = 0;
419*1fd5a2e1SPrashanth Swaminathan   if (darwin64_struct_size_exceeds_gprs_p (s, NULL, &nfp))
420*1fd5a2e1SPrashanth Swaminathan     return 0;
421*1fd5a2e1SPrashanth Swaminathan 
422*1fd5a2e1SPrashanth Swaminathan   return 1;
423*1fd5a2e1SPrashanth Swaminathan }
424*1fd5a2e1SPrashanth Swaminathan 
425*1fd5a2e1SPrashanth Swaminathan void
darwin64_pass_struct_floats(ffi_type * s,char * src,unsigned * nfpr,double ** fprs)426*1fd5a2e1SPrashanth Swaminathan darwin64_pass_struct_floats (ffi_type *s, char *src,
427*1fd5a2e1SPrashanth Swaminathan 			     unsigned *nfpr, double **fprs)
428*1fd5a2e1SPrashanth Swaminathan {
429*1fd5a2e1SPrashanth Swaminathan   int i;
430*1fd5a2e1SPrashanth Swaminathan   double *fpr_base = *fprs;
431*1fd5a2e1SPrashanth Swaminathan   unsigned struct_offset = 0;
432*1fd5a2e1SPrashanth Swaminathan 
433*1fd5a2e1SPrashanth Swaminathan   /* We don't assume anything about the alignment of the source.  */
434*1fd5a2e1SPrashanth Swaminathan   for (i = 0; s->elements[i] != NULL; i++)
435*1fd5a2e1SPrashanth Swaminathan     {
436*1fd5a2e1SPrashanth Swaminathan       char *item_base;
437*1fd5a2e1SPrashanth Swaminathan       ffi_type *p = s->elements[i];
438*1fd5a2e1SPrashanth Swaminathan       /* Find the start of this item (0 for the first one).  */
439*1fd5a2e1SPrashanth Swaminathan       if (i > 0)
440*1fd5a2e1SPrashanth Swaminathan         struct_offset = FFI_ALIGN(struct_offset, p->alignment);
441*1fd5a2e1SPrashanth Swaminathan       item_base = src + struct_offset;
442*1fd5a2e1SPrashanth Swaminathan 
443*1fd5a2e1SPrashanth Swaminathan       switch (p->type)
444*1fd5a2e1SPrashanth Swaminathan 	{
445*1fd5a2e1SPrashanth Swaminathan 	  case FFI_TYPE_STRUCT:
446*1fd5a2e1SPrashanth Swaminathan 	    darwin64_pass_struct_floats (p, item_base, nfpr,
447*1fd5a2e1SPrashanth Swaminathan 					   &fpr_base);
448*1fd5a2e1SPrashanth Swaminathan 	    break;
449*1fd5a2e1SPrashanth Swaminathan 	  case FFI_TYPE_LONGDOUBLE:
450*1fd5a2e1SPrashanth Swaminathan 	    if (*nfpr < NUM_FPR_ARG_REGISTERS)
451*1fd5a2e1SPrashanth Swaminathan 	      *fpr_base++ = *(double *)item_base;
452*1fd5a2e1SPrashanth Swaminathan 	    (*nfpr) += 1;
453*1fd5a2e1SPrashanth Swaminathan 	    item_base += 8;
454*1fd5a2e1SPrashanth Swaminathan 	  /* FALL THROUGH */
455*1fd5a2e1SPrashanth Swaminathan 	  case FFI_TYPE_DOUBLE:
456*1fd5a2e1SPrashanth Swaminathan 	    if (*nfpr < NUM_FPR_ARG_REGISTERS)
457*1fd5a2e1SPrashanth Swaminathan 	      *fpr_base++ = *(double *)item_base;
458*1fd5a2e1SPrashanth Swaminathan 	    (*nfpr) += 1;
459*1fd5a2e1SPrashanth Swaminathan 	    break;
460*1fd5a2e1SPrashanth Swaminathan 	  case FFI_TYPE_FLOAT:
461*1fd5a2e1SPrashanth Swaminathan 	    if (*nfpr < NUM_FPR_ARG_REGISTERS)
462*1fd5a2e1SPrashanth Swaminathan 	      *fpr_base++ = (double) *(float *)item_base;
463*1fd5a2e1SPrashanth Swaminathan 	    (*nfpr) += 1;
464*1fd5a2e1SPrashanth Swaminathan 	    break;
465*1fd5a2e1SPrashanth Swaminathan 	  default:
466*1fd5a2e1SPrashanth Swaminathan 	    break;
467*1fd5a2e1SPrashanth Swaminathan 	}
468*1fd5a2e1SPrashanth Swaminathan       /* now count the size of what we just used.  */
469*1fd5a2e1SPrashanth Swaminathan       struct_offset += p->size;
470*1fd5a2e1SPrashanth Swaminathan     }
471*1fd5a2e1SPrashanth Swaminathan   /* Update the scores.  */
472*1fd5a2e1SPrashanth Swaminathan   *fprs = fpr_base;
473*1fd5a2e1SPrashanth Swaminathan }
474*1fd5a2e1SPrashanth Swaminathan 
475*1fd5a2e1SPrashanth Swaminathan /* Darwin64 special rules.
476*1fd5a2e1SPrashanth Swaminathan    Break out a struct into params and float registers.  */
477*1fd5a2e1SPrashanth Swaminathan static void
darwin64_pass_struct_by_value(ffi_type * s,char * src,unsigned size,unsigned * nfpr,double ** fprs,unsigned long ** arg)478*1fd5a2e1SPrashanth Swaminathan darwin64_pass_struct_by_value (ffi_type *s, char *src, unsigned size,
479*1fd5a2e1SPrashanth Swaminathan 			       unsigned *nfpr, double **fprs, unsigned long **arg)
480*1fd5a2e1SPrashanth Swaminathan {
481*1fd5a2e1SPrashanth Swaminathan   unsigned long *next_arg = *arg;
482*1fd5a2e1SPrashanth Swaminathan   char *dest_cpy = (char *)next_arg;
483*1fd5a2e1SPrashanth Swaminathan 
484*1fd5a2e1SPrashanth Swaminathan   FFI_ASSERT (s->type == FFI_TYPE_STRUCT)
485*1fd5a2e1SPrashanth Swaminathan 
486*1fd5a2e1SPrashanth Swaminathan   if (!size)
487*1fd5a2e1SPrashanth Swaminathan     return;
488*1fd5a2e1SPrashanth Swaminathan 
489*1fd5a2e1SPrashanth Swaminathan   /* First... special cases.  */
490*1fd5a2e1SPrashanth Swaminathan   if (size < 3
491*1fd5a2e1SPrashanth Swaminathan       || (size == 4
492*1fd5a2e1SPrashanth Swaminathan 	  && s->elements[0]
493*1fd5a2e1SPrashanth Swaminathan 	  && s->elements[0]->type != FFI_TYPE_FLOAT))
494*1fd5a2e1SPrashanth Swaminathan     {
495*1fd5a2e1SPrashanth Swaminathan       /* Must be at least one GPR, padding is unspecified in value,
496*1fd5a2e1SPrashanth Swaminathan 	 let's make it zero.  */
497*1fd5a2e1SPrashanth Swaminathan       *next_arg = 0UL;
498*1fd5a2e1SPrashanth Swaminathan       dest_cpy += 8 - size;
499*1fd5a2e1SPrashanth Swaminathan       memcpy ((char *) dest_cpy, src, size);
500*1fd5a2e1SPrashanth Swaminathan       next_arg++;
501*1fd5a2e1SPrashanth Swaminathan     }
502*1fd5a2e1SPrashanth Swaminathan   else if (size == 16)
503*1fd5a2e1SPrashanth Swaminathan     {
504*1fd5a2e1SPrashanth Swaminathan       memcpy ((char *) dest_cpy, src, size);
505*1fd5a2e1SPrashanth Swaminathan       next_arg += 2;
506*1fd5a2e1SPrashanth Swaminathan     }
507*1fd5a2e1SPrashanth Swaminathan   else
508*1fd5a2e1SPrashanth Swaminathan     {
509*1fd5a2e1SPrashanth Swaminathan       /* now the general case, we consider embedded floats.  */
510*1fd5a2e1SPrashanth Swaminathan       memcpy ((char *) dest_cpy, src, size);
511*1fd5a2e1SPrashanth Swaminathan       darwin64_pass_struct_floats (s, src, nfpr, fprs);
512*1fd5a2e1SPrashanth Swaminathan       next_arg += (size+7)/8;
513*1fd5a2e1SPrashanth Swaminathan     }
514*1fd5a2e1SPrashanth Swaminathan 
515*1fd5a2e1SPrashanth Swaminathan   *arg = next_arg;
516*1fd5a2e1SPrashanth Swaminathan }
517*1fd5a2e1SPrashanth Swaminathan 
518*1fd5a2e1SPrashanth Swaminathan double *
darwin64_struct_floats_to_mem(ffi_type * s,char * dest,double * fprs,unsigned * nf)519*1fd5a2e1SPrashanth Swaminathan darwin64_struct_floats_to_mem (ffi_type *s, char *dest, double *fprs, unsigned *nf)
520*1fd5a2e1SPrashanth Swaminathan {
521*1fd5a2e1SPrashanth Swaminathan   int i;
522*1fd5a2e1SPrashanth Swaminathan   unsigned struct_offset = 0;
523*1fd5a2e1SPrashanth Swaminathan 
524*1fd5a2e1SPrashanth Swaminathan   /* We don't assume anything about the alignment of the source.  */
525*1fd5a2e1SPrashanth Swaminathan   for (i = 0; s->elements[i] != NULL; i++)
526*1fd5a2e1SPrashanth Swaminathan     {
527*1fd5a2e1SPrashanth Swaminathan       char *item_base;
528*1fd5a2e1SPrashanth Swaminathan       ffi_type *p = s->elements[i];
529*1fd5a2e1SPrashanth Swaminathan       /* Find the start of this item (0 for the first one).  */
530*1fd5a2e1SPrashanth Swaminathan       if (i > 0)
531*1fd5a2e1SPrashanth Swaminathan         struct_offset = FFI_ALIGN(struct_offset, p->alignment);
532*1fd5a2e1SPrashanth Swaminathan       item_base = dest + struct_offset;
533*1fd5a2e1SPrashanth Swaminathan 
534*1fd5a2e1SPrashanth Swaminathan       switch (p->type)
535*1fd5a2e1SPrashanth Swaminathan 	{
536*1fd5a2e1SPrashanth Swaminathan 	  case FFI_TYPE_STRUCT:
537*1fd5a2e1SPrashanth Swaminathan 	    fprs = darwin64_struct_floats_to_mem (p, item_base, fprs, nf);
538*1fd5a2e1SPrashanth Swaminathan 	    break;
539*1fd5a2e1SPrashanth Swaminathan 	  case FFI_TYPE_LONGDOUBLE:
540*1fd5a2e1SPrashanth Swaminathan 	    if (*nf < NUM_FPR_ARG_REGISTERS)
541*1fd5a2e1SPrashanth Swaminathan 	      {
542*1fd5a2e1SPrashanth Swaminathan 		*(double *)item_base = *fprs++ ;
543*1fd5a2e1SPrashanth Swaminathan 		(*nf) += 1;
544*1fd5a2e1SPrashanth Swaminathan 	      }
545*1fd5a2e1SPrashanth Swaminathan 	    item_base += 8;
546*1fd5a2e1SPrashanth Swaminathan 	  /* FALL THROUGH */
547*1fd5a2e1SPrashanth Swaminathan 	  case FFI_TYPE_DOUBLE:
548*1fd5a2e1SPrashanth Swaminathan 	    if (*nf < NUM_FPR_ARG_REGISTERS)
549*1fd5a2e1SPrashanth Swaminathan 	      {
550*1fd5a2e1SPrashanth Swaminathan 		*(double *)item_base = *fprs++ ;
551*1fd5a2e1SPrashanth Swaminathan 		(*nf) += 1;
552*1fd5a2e1SPrashanth Swaminathan 	      }
553*1fd5a2e1SPrashanth Swaminathan 	    break;
554*1fd5a2e1SPrashanth Swaminathan 	  case FFI_TYPE_FLOAT:
555*1fd5a2e1SPrashanth Swaminathan 	    if (*nf < NUM_FPR_ARG_REGISTERS)
556*1fd5a2e1SPrashanth Swaminathan 	      {
557*1fd5a2e1SPrashanth Swaminathan 		*(float *)item_base = (float) *fprs++ ;
558*1fd5a2e1SPrashanth Swaminathan 		(*nf) += 1;
559*1fd5a2e1SPrashanth Swaminathan 	      }
560*1fd5a2e1SPrashanth Swaminathan 	    break;
561*1fd5a2e1SPrashanth Swaminathan 	  default:
562*1fd5a2e1SPrashanth Swaminathan 	    break;
563*1fd5a2e1SPrashanth Swaminathan 	}
564*1fd5a2e1SPrashanth Swaminathan       /* now count the size of what we just used.  */
565*1fd5a2e1SPrashanth Swaminathan       struct_offset += p->size;
566*1fd5a2e1SPrashanth Swaminathan     }
567*1fd5a2e1SPrashanth Swaminathan   return fprs;
568*1fd5a2e1SPrashanth Swaminathan }
569*1fd5a2e1SPrashanth Swaminathan 
570*1fd5a2e1SPrashanth Swaminathan #endif
571*1fd5a2e1SPrashanth Swaminathan 
572*1fd5a2e1SPrashanth Swaminathan /* Adjust the size of S to be correct for Darwin.
573*1fd5a2e1SPrashanth Swaminathan    On Darwin m32, the first field of a structure has natural alignment.
574*1fd5a2e1SPrashanth Swaminathan    On Darwin m64, all fields have natural alignment.  */
575*1fd5a2e1SPrashanth Swaminathan 
576*1fd5a2e1SPrashanth Swaminathan static void
darwin_adjust_aggregate_sizes(ffi_type * s)577*1fd5a2e1SPrashanth Swaminathan darwin_adjust_aggregate_sizes (ffi_type *s)
578*1fd5a2e1SPrashanth Swaminathan {
579*1fd5a2e1SPrashanth Swaminathan   int i;
580*1fd5a2e1SPrashanth Swaminathan 
581*1fd5a2e1SPrashanth Swaminathan   if (s->type != FFI_TYPE_STRUCT)
582*1fd5a2e1SPrashanth Swaminathan     return;
583*1fd5a2e1SPrashanth Swaminathan 
584*1fd5a2e1SPrashanth Swaminathan   s->size = 0;
585*1fd5a2e1SPrashanth Swaminathan   for (i = 0; s->elements[i] != NULL; i++)
586*1fd5a2e1SPrashanth Swaminathan     {
587*1fd5a2e1SPrashanth Swaminathan       ffi_type *p;
588*1fd5a2e1SPrashanth Swaminathan       int align;
589*1fd5a2e1SPrashanth Swaminathan 
590*1fd5a2e1SPrashanth Swaminathan       p = s->elements[i];
591*1fd5a2e1SPrashanth Swaminathan       if (p->type == FFI_TYPE_STRUCT)
592*1fd5a2e1SPrashanth Swaminathan 	darwin_adjust_aggregate_sizes (p);
593*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
594*1fd5a2e1SPrashanth Swaminathan       /* Natural alignment for all items.  */
595*1fd5a2e1SPrashanth Swaminathan       align = p->alignment;
596*1fd5a2e1SPrashanth Swaminathan #else
597*1fd5a2e1SPrashanth Swaminathan       /* Natural alignment for the first item... */
598*1fd5a2e1SPrashanth Swaminathan       if (i == 0)
599*1fd5a2e1SPrashanth Swaminathan 	align = p->alignment;
600*1fd5a2e1SPrashanth Swaminathan       else if (p->alignment == 16 || p->alignment < 4)
601*1fd5a2e1SPrashanth Swaminathan 	/* .. subsequent items with vector or align < 4 have natural align.  */
602*1fd5a2e1SPrashanth Swaminathan 	align = p->alignment;
603*1fd5a2e1SPrashanth Swaminathan       else
604*1fd5a2e1SPrashanth Swaminathan 	/* .. or align is 4.  */
605*1fd5a2e1SPrashanth Swaminathan 	align = 4;
606*1fd5a2e1SPrashanth Swaminathan #endif
607*1fd5a2e1SPrashanth Swaminathan       /* Pad, if necessary, before adding the current item.  */
608*1fd5a2e1SPrashanth Swaminathan       s->size = FFI_ALIGN(s->size, align) + p->size;
609*1fd5a2e1SPrashanth Swaminathan     }
610*1fd5a2e1SPrashanth Swaminathan 
611*1fd5a2e1SPrashanth Swaminathan   s->size = FFI_ALIGN(s->size, s->alignment);
612*1fd5a2e1SPrashanth Swaminathan 
613*1fd5a2e1SPrashanth Swaminathan   /* This should not be necessary on m64, but harmless.  */
614*1fd5a2e1SPrashanth Swaminathan   if (s->elements[0]->type == FFI_TYPE_UINT64
615*1fd5a2e1SPrashanth Swaminathan       || s->elements[0]->type == FFI_TYPE_SINT64
616*1fd5a2e1SPrashanth Swaminathan       || s->elements[0]->type == FFI_TYPE_DOUBLE
617*1fd5a2e1SPrashanth Swaminathan       || s->elements[0]->alignment == 8)
618*1fd5a2e1SPrashanth Swaminathan     s->alignment = s->alignment > 8 ? s->alignment : 8;
619*1fd5a2e1SPrashanth Swaminathan   /* Do not add additional tail padding.  */
620*1fd5a2e1SPrashanth Swaminathan }
621*1fd5a2e1SPrashanth Swaminathan 
622*1fd5a2e1SPrashanth Swaminathan /* Adjust the size of S to be correct for AIX.
623*1fd5a2e1SPrashanth Swaminathan    Word-align double unless it is the first member of a structure.  */
624*1fd5a2e1SPrashanth Swaminathan 
625*1fd5a2e1SPrashanth Swaminathan static void
aix_adjust_aggregate_sizes(ffi_type * s)626*1fd5a2e1SPrashanth Swaminathan aix_adjust_aggregate_sizes (ffi_type *s)
627*1fd5a2e1SPrashanth Swaminathan {
628*1fd5a2e1SPrashanth Swaminathan   int i;
629*1fd5a2e1SPrashanth Swaminathan 
630*1fd5a2e1SPrashanth Swaminathan   if (s->type != FFI_TYPE_STRUCT)
631*1fd5a2e1SPrashanth Swaminathan     return;
632*1fd5a2e1SPrashanth Swaminathan 
633*1fd5a2e1SPrashanth Swaminathan   s->size = 0;
634*1fd5a2e1SPrashanth Swaminathan   for (i = 0; s->elements[i] != NULL; i++)
635*1fd5a2e1SPrashanth Swaminathan     {
636*1fd5a2e1SPrashanth Swaminathan       ffi_type *p;
637*1fd5a2e1SPrashanth Swaminathan       int align;
638*1fd5a2e1SPrashanth Swaminathan 
639*1fd5a2e1SPrashanth Swaminathan       p = s->elements[i];
640*1fd5a2e1SPrashanth Swaminathan       aix_adjust_aggregate_sizes (p);
641*1fd5a2e1SPrashanth Swaminathan       align = p->alignment;
642*1fd5a2e1SPrashanth Swaminathan       if (i != 0 && p->type == FFI_TYPE_DOUBLE)
643*1fd5a2e1SPrashanth Swaminathan 	align = 4;
644*1fd5a2e1SPrashanth Swaminathan       s->size = FFI_ALIGN(s->size, align) + p->size;
645*1fd5a2e1SPrashanth Swaminathan     }
646*1fd5a2e1SPrashanth Swaminathan 
647*1fd5a2e1SPrashanth Swaminathan   s->size = FFI_ALIGN(s->size, s->alignment);
648*1fd5a2e1SPrashanth Swaminathan 
649*1fd5a2e1SPrashanth Swaminathan   if (s->elements[0]->type == FFI_TYPE_UINT64
650*1fd5a2e1SPrashanth Swaminathan       || s->elements[0]->type == FFI_TYPE_SINT64
651*1fd5a2e1SPrashanth Swaminathan       || s->elements[0]->type == FFI_TYPE_DOUBLE
652*1fd5a2e1SPrashanth Swaminathan       || s->elements[0]->alignment == 8)
653*1fd5a2e1SPrashanth Swaminathan     s->alignment = s->alignment > 8 ? s->alignment : 8;
654*1fd5a2e1SPrashanth Swaminathan   /* Do not add additional tail padding.  */
655*1fd5a2e1SPrashanth Swaminathan }
656*1fd5a2e1SPrashanth Swaminathan 
657*1fd5a2e1SPrashanth Swaminathan /* Perform machine dependent cif processing.  */
658*1fd5a2e1SPrashanth Swaminathan ffi_status
ffi_prep_cif_machdep(ffi_cif * cif)659*1fd5a2e1SPrashanth Swaminathan ffi_prep_cif_machdep (ffi_cif *cif)
660*1fd5a2e1SPrashanth Swaminathan {
661*1fd5a2e1SPrashanth Swaminathan   /* All this is for the DARWIN ABI.  */
662*1fd5a2e1SPrashanth Swaminathan   unsigned i;
663*1fd5a2e1SPrashanth Swaminathan   ffi_type **ptr;
664*1fd5a2e1SPrashanth Swaminathan   unsigned bytes;
665*1fd5a2e1SPrashanth Swaminathan   unsigned fparg_count = 0, intarg_count = 0;
666*1fd5a2e1SPrashanth Swaminathan   unsigned flags = 0;
667*1fd5a2e1SPrashanth Swaminathan   unsigned size_al = 0;
668*1fd5a2e1SPrashanth Swaminathan 
669*1fd5a2e1SPrashanth Swaminathan   /* All the machine-independent calculation of cif->bytes will be wrong.
670*1fd5a2e1SPrashanth Swaminathan      All the calculation of structure sizes will also be wrong.
671*1fd5a2e1SPrashanth Swaminathan      Redo the calculation for DARWIN.  */
672*1fd5a2e1SPrashanth Swaminathan 
673*1fd5a2e1SPrashanth Swaminathan   if (cif->abi == FFI_DARWIN)
674*1fd5a2e1SPrashanth Swaminathan     {
675*1fd5a2e1SPrashanth Swaminathan       darwin_adjust_aggregate_sizes (cif->rtype);
676*1fd5a2e1SPrashanth Swaminathan       for (i = 0; i < cif->nargs; i++)
677*1fd5a2e1SPrashanth Swaminathan 	darwin_adjust_aggregate_sizes (cif->arg_types[i]);
678*1fd5a2e1SPrashanth Swaminathan     }
679*1fd5a2e1SPrashanth Swaminathan 
680*1fd5a2e1SPrashanth Swaminathan   if (cif->abi == FFI_AIX)
681*1fd5a2e1SPrashanth Swaminathan     {
682*1fd5a2e1SPrashanth Swaminathan       aix_adjust_aggregate_sizes (cif->rtype);
683*1fd5a2e1SPrashanth Swaminathan       for (i = 0; i < cif->nargs; i++)
684*1fd5a2e1SPrashanth Swaminathan 	aix_adjust_aggregate_sizes (cif->arg_types[i]);
685*1fd5a2e1SPrashanth Swaminathan     }
686*1fd5a2e1SPrashanth Swaminathan 
687*1fd5a2e1SPrashanth Swaminathan   /* Space for the frame pointer, callee's LR, CR, etc, and for
688*1fd5a2e1SPrashanth Swaminathan      the asm's temp regs.  */
689*1fd5a2e1SPrashanth Swaminathan 
690*1fd5a2e1SPrashanth Swaminathan   bytes = (LINKAGE_AREA_GPRS + ASM_NEEDS_REGISTERS) * sizeof(unsigned long);
691*1fd5a2e1SPrashanth Swaminathan 
692*1fd5a2e1SPrashanth Swaminathan   /* Return value handling.
693*1fd5a2e1SPrashanth Swaminathan     The rules m32 are as follows:
694*1fd5a2e1SPrashanth Swaminathan      - 32-bit (or less) integer values are returned in gpr3;
695*1fd5a2e1SPrashanth Swaminathan      - structures of size <= 4 bytes also returned in gpr3;
696*1fd5a2e1SPrashanth Swaminathan      - 64-bit integer values [??? and structures between 5 and 8 bytes] are
697*1fd5a2e1SPrashanth Swaminathan        returned in gpr3 and gpr4;
698*1fd5a2e1SPrashanth Swaminathan      - Single/double FP values are returned in fpr1;
699*1fd5a2e1SPrashanth Swaminathan      - Long double FP (if not equivalent to double) values are returned in
700*1fd5a2e1SPrashanth Swaminathan        fpr1 and fpr2;
701*1fd5a2e1SPrashanth Swaminathan      m64:
702*1fd5a2e1SPrashanth Swaminathan      - 64-bit or smaller integral values are returned in GPR3
703*1fd5a2e1SPrashanth Swaminathan      - Single/double FP values are returned in fpr1;
704*1fd5a2e1SPrashanth Swaminathan      - Long double FP values are returned in fpr1 and fpr2;
705*1fd5a2e1SPrashanth Swaminathan      m64 Structures:
706*1fd5a2e1SPrashanth Swaminathan      - If the structure could be accommodated in registers were it to be the
707*1fd5a2e1SPrashanth Swaminathan        first argument to a routine, then it is returned in those registers.
708*1fd5a2e1SPrashanth Swaminathan      m32/m64 structures otherwise:
709*1fd5a2e1SPrashanth Swaminathan      - Larger structures values are allocated space and a pointer is passed
710*1fd5a2e1SPrashanth Swaminathan        as the first argument.  */
711*1fd5a2e1SPrashanth Swaminathan   switch (cif->rtype->type)
712*1fd5a2e1SPrashanth Swaminathan     {
713*1fd5a2e1SPrashanth Swaminathan 
714*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
715*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_LONGDOUBLE:
716*1fd5a2e1SPrashanth Swaminathan       flags |= FLAG_RETURNS_128BITS;
717*1fd5a2e1SPrashanth Swaminathan       flags |= FLAG_RETURNS_FP;
718*1fd5a2e1SPrashanth Swaminathan       break;
719*1fd5a2e1SPrashanth Swaminathan #endif
720*1fd5a2e1SPrashanth Swaminathan 
721*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_DOUBLE:
722*1fd5a2e1SPrashanth Swaminathan       flags |= FLAG_RETURNS_64BITS;
723*1fd5a2e1SPrashanth Swaminathan       /* Fall through.  */
724*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_FLOAT:
725*1fd5a2e1SPrashanth Swaminathan       flags |= FLAG_RETURNS_FP;
726*1fd5a2e1SPrashanth Swaminathan       break;
727*1fd5a2e1SPrashanth Swaminathan 
728*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_UINT64:
729*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_SINT64:
730*1fd5a2e1SPrashanth Swaminathan #ifdef POWERPC64
731*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_POINTER:
732*1fd5a2e1SPrashanth Swaminathan #endif
733*1fd5a2e1SPrashanth Swaminathan       flags |= FLAG_RETURNS_64BITS;
734*1fd5a2e1SPrashanth Swaminathan       break;
735*1fd5a2e1SPrashanth Swaminathan 
736*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_STRUCT:
737*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
738*1fd5a2e1SPrashanth Swaminathan       {
739*1fd5a2e1SPrashanth Swaminathan 	/* Can we fit the struct into regs?  */
740*1fd5a2e1SPrashanth Swaminathan 	if (darwin64_struct_ret_by_value_p (cif->rtype))
741*1fd5a2e1SPrashanth Swaminathan 	  {
742*1fd5a2e1SPrashanth Swaminathan 	    unsigned nfpr = 0;
743*1fd5a2e1SPrashanth Swaminathan 	    flags |= FLAG_RETURNS_STRUCT;
744*1fd5a2e1SPrashanth Swaminathan 	    if (cif->rtype->size != 16)
745*1fd5a2e1SPrashanth Swaminathan 	      darwin64_scan_struct_for_floats (cif->rtype, &nfpr) ;
746*1fd5a2e1SPrashanth Swaminathan 	    else
747*1fd5a2e1SPrashanth Swaminathan 	      flags |= FLAG_RETURNS_128BITS;
748*1fd5a2e1SPrashanth Swaminathan 	    /* Will be 0 for 16byte struct.  */
749*1fd5a2e1SPrashanth Swaminathan 	    if (nfpr)
750*1fd5a2e1SPrashanth Swaminathan 	      flags |= FLAG_RETURNS_FP;
751*1fd5a2e1SPrashanth Swaminathan 	  }
752*1fd5a2e1SPrashanth Swaminathan 	else /* By ref. */
753*1fd5a2e1SPrashanth Swaminathan 	  {
754*1fd5a2e1SPrashanth Swaminathan 	    flags |= FLAG_RETVAL_REFERENCE;
755*1fd5a2e1SPrashanth Swaminathan 	    flags |= FLAG_RETURNS_NOTHING;
756*1fd5a2e1SPrashanth Swaminathan 	    intarg_count++;
757*1fd5a2e1SPrashanth Swaminathan 	  }
758*1fd5a2e1SPrashanth Swaminathan       }
759*1fd5a2e1SPrashanth Swaminathan #elif defined(DARWIN_PPC)
760*1fd5a2e1SPrashanth Swaminathan       if (cif->rtype->size <= 4)
761*1fd5a2e1SPrashanth Swaminathan 	flags |= FLAG_RETURNS_STRUCT;
762*1fd5a2e1SPrashanth Swaminathan       else /* else by reference.  */
763*1fd5a2e1SPrashanth Swaminathan 	{
764*1fd5a2e1SPrashanth Swaminathan 	  flags |= FLAG_RETVAL_REFERENCE;
765*1fd5a2e1SPrashanth Swaminathan 	  flags |= FLAG_RETURNS_NOTHING;
766*1fd5a2e1SPrashanth Swaminathan 	  intarg_count++;
767*1fd5a2e1SPrashanth Swaminathan 	}
768*1fd5a2e1SPrashanth Swaminathan #else /* assume we pass by ref.  */
769*1fd5a2e1SPrashanth Swaminathan       flags |= FLAG_RETVAL_REFERENCE;
770*1fd5a2e1SPrashanth Swaminathan       flags |= FLAG_RETURNS_NOTHING;
771*1fd5a2e1SPrashanth Swaminathan       intarg_count++;
772*1fd5a2e1SPrashanth Swaminathan #endif
773*1fd5a2e1SPrashanth Swaminathan       break;
774*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_VOID:
775*1fd5a2e1SPrashanth Swaminathan       flags |= FLAG_RETURNS_NOTHING;
776*1fd5a2e1SPrashanth Swaminathan       break;
777*1fd5a2e1SPrashanth Swaminathan 
778*1fd5a2e1SPrashanth Swaminathan     default:
779*1fd5a2e1SPrashanth Swaminathan       /* Returns 32-bit integer, or similar.  Nothing to do here.  */
780*1fd5a2e1SPrashanth Swaminathan       break;
781*1fd5a2e1SPrashanth Swaminathan     }
782*1fd5a2e1SPrashanth Swaminathan 
783*1fd5a2e1SPrashanth Swaminathan   /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
784*1fd5a2e1SPrashanth Swaminathan      first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
785*1fd5a2e1SPrashanth Swaminathan      goes on the stack.
786*1fd5a2e1SPrashanth Swaminathan      ??? Structures are passed as a pointer to a copy of the structure.
787*1fd5a2e1SPrashanth Swaminathan      Stuff on the stack needs to keep proper alignment.
788*1fd5a2e1SPrashanth Swaminathan      For m64 the count is effectively of half-GPRs.  */
789*1fd5a2e1SPrashanth Swaminathan   for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
790*1fd5a2e1SPrashanth Swaminathan     {
791*1fd5a2e1SPrashanth Swaminathan       unsigned align_words;
792*1fd5a2e1SPrashanth Swaminathan       switch ((*ptr)->type)
793*1fd5a2e1SPrashanth Swaminathan 	{
794*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_FLOAT:
795*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_DOUBLE:
796*1fd5a2e1SPrashanth Swaminathan 	  fparg_count++;
797*1fd5a2e1SPrashanth Swaminathan #if !defined(POWERPC_DARWIN64)
798*1fd5a2e1SPrashanth Swaminathan 	  /* If this FP arg is going on the stack, it must be
799*1fd5a2e1SPrashanth Swaminathan 	     8-byte-aligned.  */
800*1fd5a2e1SPrashanth Swaminathan 	  if (fparg_count > NUM_FPR_ARG_REGISTERS
801*1fd5a2e1SPrashanth Swaminathan 	      && (intarg_count & 0x01) != 0)
802*1fd5a2e1SPrashanth Swaminathan 	    intarg_count++;
803*1fd5a2e1SPrashanth Swaminathan #endif
804*1fd5a2e1SPrashanth Swaminathan 	  break;
805*1fd5a2e1SPrashanth Swaminathan 
806*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
807*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_LONGDOUBLE:
808*1fd5a2e1SPrashanth Swaminathan 	  fparg_count += 2;
809*1fd5a2e1SPrashanth Swaminathan 	  /* If this FP arg is going on the stack, it must be
810*1fd5a2e1SPrashanth Swaminathan 	     16-byte-aligned.  */
811*1fd5a2e1SPrashanth Swaminathan 	  if (fparg_count >= NUM_FPR_ARG_REGISTERS)
812*1fd5a2e1SPrashanth Swaminathan #if defined (POWERPC64)
813*1fd5a2e1SPrashanth Swaminathan 	    intarg_count = FFI_ALIGN(intarg_count, 2);
814*1fd5a2e1SPrashanth Swaminathan #else
815*1fd5a2e1SPrashanth Swaminathan 	    intarg_count = FFI_ALIGN(intarg_count, 4);
816*1fd5a2e1SPrashanth Swaminathan #endif
817*1fd5a2e1SPrashanth Swaminathan 	  break;
818*1fd5a2e1SPrashanth Swaminathan #endif
819*1fd5a2e1SPrashanth Swaminathan 
820*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT64:
821*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT64:
822*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC64)
823*1fd5a2e1SPrashanth Swaminathan 	  intarg_count++;
824*1fd5a2e1SPrashanth Swaminathan #else
825*1fd5a2e1SPrashanth Swaminathan 	  /* 'long long' arguments are passed as two words, but
826*1fd5a2e1SPrashanth Swaminathan 	     either both words must fit in registers or both go
827*1fd5a2e1SPrashanth Swaminathan 	     on the stack.  If they go on the stack, they must
828*1fd5a2e1SPrashanth Swaminathan 	     be 8-byte-aligned.  */
829*1fd5a2e1SPrashanth Swaminathan 	  if (intarg_count == NUM_GPR_ARG_REGISTERS-1
830*1fd5a2e1SPrashanth Swaminathan 	      || (intarg_count >= NUM_GPR_ARG_REGISTERS
831*1fd5a2e1SPrashanth Swaminathan 	          && (intarg_count & 0x01) != 0))
832*1fd5a2e1SPrashanth Swaminathan 	    intarg_count++;
833*1fd5a2e1SPrashanth Swaminathan 	  intarg_count += 2;
834*1fd5a2e1SPrashanth Swaminathan #endif
835*1fd5a2e1SPrashanth Swaminathan 	  break;
836*1fd5a2e1SPrashanth Swaminathan 
837*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_STRUCT:
838*1fd5a2e1SPrashanth Swaminathan 	  size_al = (*ptr)->size;
839*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
840*1fd5a2e1SPrashanth Swaminathan 	  align_words = (*ptr)->alignment >> 3;
841*1fd5a2e1SPrashanth Swaminathan 	  if (align_words)
842*1fd5a2e1SPrashanth Swaminathan 	    intarg_count = FFI_ALIGN(intarg_count, align_words);
843*1fd5a2e1SPrashanth Swaminathan 	  /* Base size of the struct.  */
844*1fd5a2e1SPrashanth Swaminathan 	  intarg_count += (size_al + 7) / 8;
845*1fd5a2e1SPrashanth Swaminathan 	  /* If 16 bytes then don't worry about floats.  */
846*1fd5a2e1SPrashanth Swaminathan 	  if (size_al != 16)
847*1fd5a2e1SPrashanth Swaminathan 	    /* Scan through for floats to be placed in regs.  */
848*1fd5a2e1SPrashanth Swaminathan 	    darwin64_scan_struct_for_floats (*ptr, &fparg_count) ;
849*1fd5a2e1SPrashanth Swaminathan #else
850*1fd5a2e1SPrashanth Swaminathan 	  align_words = (*ptr)->alignment >> 2;
851*1fd5a2e1SPrashanth Swaminathan 	  if (align_words)
852*1fd5a2e1SPrashanth Swaminathan 	    intarg_count = FFI_ALIGN(intarg_count, align_words);
853*1fd5a2e1SPrashanth Swaminathan 	  /* If the first member of the struct is a double, then align
854*1fd5a2e1SPrashanth Swaminathan 	     the struct to double-word.
855*1fd5a2e1SPrashanth Swaminathan 	  if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE)
856*1fd5a2e1SPrashanth Swaminathan 	    size_al = FFI_ALIGN((*ptr)->size, 8); */
857*1fd5a2e1SPrashanth Swaminathan #  ifdef POWERPC64
858*1fd5a2e1SPrashanth Swaminathan 	  intarg_count += (size_al + 7) / 8;
859*1fd5a2e1SPrashanth Swaminathan #  else
860*1fd5a2e1SPrashanth Swaminathan 	  intarg_count += (size_al + 3) / 4;
861*1fd5a2e1SPrashanth Swaminathan #  endif
862*1fd5a2e1SPrashanth Swaminathan #endif
863*1fd5a2e1SPrashanth Swaminathan 	  break;
864*1fd5a2e1SPrashanth Swaminathan 
865*1fd5a2e1SPrashanth Swaminathan 	default:
866*1fd5a2e1SPrashanth Swaminathan 	  /* Everything else is passed as a 4-byte word in a GPR, either
867*1fd5a2e1SPrashanth Swaminathan 	     the object itself or a pointer to it.  */
868*1fd5a2e1SPrashanth Swaminathan 	  intarg_count++;
869*1fd5a2e1SPrashanth Swaminathan 	  break;
870*1fd5a2e1SPrashanth Swaminathan 	}
871*1fd5a2e1SPrashanth Swaminathan     }
872*1fd5a2e1SPrashanth Swaminathan 
873*1fd5a2e1SPrashanth Swaminathan   if (fparg_count != 0)
874*1fd5a2e1SPrashanth Swaminathan     flags |= FLAG_FP_ARGUMENTS;
875*1fd5a2e1SPrashanth Swaminathan 
876*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
877*1fd5a2e1SPrashanth Swaminathan   /* Space to image the FPR registers, if needed - which includes when they might be
878*1fd5a2e1SPrashanth Swaminathan      used in a struct return.  */
879*1fd5a2e1SPrashanth Swaminathan   if (fparg_count != 0
880*1fd5a2e1SPrashanth Swaminathan       || ((flags & FLAG_RETURNS_STRUCT)
881*1fd5a2e1SPrashanth Swaminathan 	   && (flags & FLAG_RETURNS_FP)))
882*1fd5a2e1SPrashanth Swaminathan     bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
883*1fd5a2e1SPrashanth Swaminathan #else
884*1fd5a2e1SPrashanth Swaminathan   /* Space for the FPR registers, if needed.  */
885*1fd5a2e1SPrashanth Swaminathan   if (fparg_count != 0)
886*1fd5a2e1SPrashanth Swaminathan     bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
887*1fd5a2e1SPrashanth Swaminathan #endif
888*1fd5a2e1SPrashanth Swaminathan 
889*1fd5a2e1SPrashanth Swaminathan   /* Stack space.  */
890*1fd5a2e1SPrashanth Swaminathan #ifdef POWERPC64
891*1fd5a2e1SPrashanth Swaminathan   if ((intarg_count + fparg_count) > NUM_GPR_ARG_REGISTERS)
892*1fd5a2e1SPrashanth Swaminathan     bytes += (intarg_count + fparg_count) * sizeof(long);
893*1fd5a2e1SPrashanth Swaminathan #else
894*1fd5a2e1SPrashanth Swaminathan   if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS)
895*1fd5a2e1SPrashanth Swaminathan     bytes += (intarg_count + 2 * fparg_count) * sizeof(long);
896*1fd5a2e1SPrashanth Swaminathan #endif
897*1fd5a2e1SPrashanth Swaminathan   else
898*1fd5a2e1SPrashanth Swaminathan     bytes += NUM_GPR_ARG_REGISTERS * sizeof(long);
899*1fd5a2e1SPrashanth Swaminathan 
900*1fd5a2e1SPrashanth Swaminathan   /* The stack space allocated needs to be a multiple of 16 bytes.  */
901*1fd5a2e1SPrashanth Swaminathan   bytes = FFI_ALIGN(bytes, 16) ;
902*1fd5a2e1SPrashanth Swaminathan 
903*1fd5a2e1SPrashanth Swaminathan   cif->flags = flags;
904*1fd5a2e1SPrashanth Swaminathan   cif->bytes = bytes;
905*1fd5a2e1SPrashanth Swaminathan 
906*1fd5a2e1SPrashanth Swaminathan   return FFI_OK;
907*1fd5a2e1SPrashanth Swaminathan }
908*1fd5a2e1SPrashanth Swaminathan 
909*1fd5a2e1SPrashanth Swaminathan extern void ffi_call_AIX(extended_cif *, long, unsigned, unsigned *,
910*1fd5a2e1SPrashanth Swaminathan 			 void (*fn)(void), void (*fn2)(void));
911*1fd5a2e1SPrashanth Swaminathan 
912*1fd5a2e1SPrashanth Swaminathan extern void ffi_call_go_AIX(extended_cif *, long, unsigned, unsigned *,
913*1fd5a2e1SPrashanth Swaminathan 			    void (*fn)(void), void (*fn2)(void), void *closure);
914*1fd5a2e1SPrashanth Swaminathan 
915*1fd5a2e1SPrashanth Swaminathan extern void ffi_call_DARWIN(extended_cif *, long, unsigned, unsigned *,
916*1fd5a2e1SPrashanth Swaminathan 			    void (*fn)(void), void (*fn2)(void), ffi_type*);
917*1fd5a2e1SPrashanth Swaminathan 
918*1fd5a2e1SPrashanth Swaminathan void
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)919*1fd5a2e1SPrashanth Swaminathan ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
920*1fd5a2e1SPrashanth Swaminathan {
921*1fd5a2e1SPrashanth Swaminathan   extended_cif ecif;
922*1fd5a2e1SPrashanth Swaminathan 
923*1fd5a2e1SPrashanth Swaminathan   ecif.cif = cif;
924*1fd5a2e1SPrashanth Swaminathan   ecif.avalue = avalue;
925*1fd5a2e1SPrashanth Swaminathan 
926*1fd5a2e1SPrashanth Swaminathan   /* If the return value is a struct and we don't have a return
927*1fd5a2e1SPrashanth Swaminathan      value address then we need to make one.  */
928*1fd5a2e1SPrashanth Swaminathan 
929*1fd5a2e1SPrashanth Swaminathan   if ((rvalue == NULL) &&
930*1fd5a2e1SPrashanth Swaminathan       (cif->rtype->type == FFI_TYPE_STRUCT))
931*1fd5a2e1SPrashanth Swaminathan     {
932*1fd5a2e1SPrashanth Swaminathan       ecif.rvalue = alloca (cif->rtype->size);
933*1fd5a2e1SPrashanth Swaminathan     }
934*1fd5a2e1SPrashanth Swaminathan   else
935*1fd5a2e1SPrashanth Swaminathan     ecif.rvalue = rvalue;
936*1fd5a2e1SPrashanth Swaminathan 
937*1fd5a2e1SPrashanth Swaminathan   switch (cif->abi)
938*1fd5a2e1SPrashanth Swaminathan     {
939*1fd5a2e1SPrashanth Swaminathan     case FFI_AIX:
940*1fd5a2e1SPrashanth Swaminathan       ffi_call_AIX(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn,
941*1fd5a2e1SPrashanth Swaminathan 		   FFI_FN(ffi_prep_args));
942*1fd5a2e1SPrashanth Swaminathan       break;
943*1fd5a2e1SPrashanth Swaminathan     case FFI_DARWIN:
944*1fd5a2e1SPrashanth Swaminathan       ffi_call_DARWIN(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn,
945*1fd5a2e1SPrashanth Swaminathan 		      FFI_FN(ffi_prep_args), cif->rtype);
946*1fd5a2e1SPrashanth Swaminathan       break;
947*1fd5a2e1SPrashanth Swaminathan     default:
948*1fd5a2e1SPrashanth Swaminathan       FFI_ASSERT(0);
949*1fd5a2e1SPrashanth Swaminathan       break;
950*1fd5a2e1SPrashanth Swaminathan     }
951*1fd5a2e1SPrashanth Swaminathan }
952*1fd5a2e1SPrashanth Swaminathan 
953*1fd5a2e1SPrashanth Swaminathan void
ffi_call_go(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue,void * closure)954*1fd5a2e1SPrashanth Swaminathan ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue,
955*1fd5a2e1SPrashanth Swaminathan 	     void *closure)
956*1fd5a2e1SPrashanth Swaminathan {
957*1fd5a2e1SPrashanth Swaminathan   extended_cif ecif;
958*1fd5a2e1SPrashanth Swaminathan 
959*1fd5a2e1SPrashanth Swaminathan   ecif.cif = cif;
960*1fd5a2e1SPrashanth Swaminathan   ecif.avalue = avalue;
961*1fd5a2e1SPrashanth Swaminathan 
962*1fd5a2e1SPrashanth Swaminathan   /* If the return value is a struct and we don't have a return
963*1fd5a2e1SPrashanth Swaminathan      value address then we need to make one.  */
964*1fd5a2e1SPrashanth Swaminathan 
965*1fd5a2e1SPrashanth Swaminathan   if ((rvalue == NULL) &&
966*1fd5a2e1SPrashanth Swaminathan       (cif->rtype->type == FFI_TYPE_STRUCT))
967*1fd5a2e1SPrashanth Swaminathan     {
968*1fd5a2e1SPrashanth Swaminathan       ecif.rvalue = alloca (cif->rtype->size);
969*1fd5a2e1SPrashanth Swaminathan     }
970*1fd5a2e1SPrashanth Swaminathan   else
971*1fd5a2e1SPrashanth Swaminathan     ecif.rvalue = rvalue;
972*1fd5a2e1SPrashanth Swaminathan 
973*1fd5a2e1SPrashanth Swaminathan   switch (cif->abi)
974*1fd5a2e1SPrashanth Swaminathan     {
975*1fd5a2e1SPrashanth Swaminathan     case FFI_AIX:
976*1fd5a2e1SPrashanth Swaminathan       ffi_call_go_AIX(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn,
977*1fd5a2e1SPrashanth Swaminathan 		      FFI_FN(ffi_prep_args), closure);
978*1fd5a2e1SPrashanth Swaminathan       break;
979*1fd5a2e1SPrashanth Swaminathan     default:
980*1fd5a2e1SPrashanth Swaminathan       FFI_ASSERT(0);
981*1fd5a2e1SPrashanth Swaminathan       break;
982*1fd5a2e1SPrashanth Swaminathan     }
983*1fd5a2e1SPrashanth Swaminathan }
984*1fd5a2e1SPrashanth Swaminathan 
985*1fd5a2e1SPrashanth Swaminathan static void flush_icache(char *);
986*1fd5a2e1SPrashanth Swaminathan static void flush_range(char *, int);
987*1fd5a2e1SPrashanth Swaminathan 
988*1fd5a2e1SPrashanth Swaminathan /* The layout of a function descriptor.  A C function pointer really
989*1fd5a2e1SPrashanth Swaminathan    points to one of these.  */
990*1fd5a2e1SPrashanth Swaminathan 
991*1fd5a2e1SPrashanth Swaminathan typedef struct aix_fd_struct {
992*1fd5a2e1SPrashanth Swaminathan   void *code_pointer;
993*1fd5a2e1SPrashanth Swaminathan   void *toc;
994*1fd5a2e1SPrashanth Swaminathan } aix_fd;
995*1fd5a2e1SPrashanth Swaminathan 
996*1fd5a2e1SPrashanth Swaminathan /* here I'd like to add the stack frame layout we use in darwin_closure.S
997*1fd5a2e1SPrashanth Swaminathan    and aix_closure.S
998*1fd5a2e1SPrashanth Swaminathan 
999*1fd5a2e1SPrashanth Swaminathan    m32/m64
1000*1fd5a2e1SPrashanth Swaminathan 
1001*1fd5a2e1SPrashanth Swaminathan    The stack layout looks like this:
1002*1fd5a2e1SPrashanth Swaminathan 
1003*1fd5a2e1SPrashanth Swaminathan    |   Additional params...			| |     Higher address
1004*1fd5a2e1SPrashanth Swaminathan    ~						~ ~
1005*1fd5a2e1SPrashanth Swaminathan    |   Parameters      (at least 8*4/8=32/64)	| | NUM_GPR_ARG_REGISTERS
1006*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |
1007*1fd5a2e1SPrashanth Swaminathan    |   TOC=R2 (AIX) Reserved (Darwin)   4/8	| |
1008*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |
1009*1fd5a2e1SPrashanth Swaminathan    |   Reserved                       2*4/8	| |
1010*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |
1011*1fd5a2e1SPrashanth Swaminathan    |   Space for callee's LR		4/8	| |
1012*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |
1013*1fd5a2e1SPrashanth Swaminathan    |   Saved CR [low word for m64]      4/8	| |
1014*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |
1015*1fd5a2e1SPrashanth Swaminathan    |   Current backchain pointer	4/8	|-/ Parent's frame.
1016*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| <+ <<< on entry to ffi_closure_ASM
1017*1fd5a2e1SPrashanth Swaminathan    |   Result Bytes			16	| |
1018*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |
1019*1fd5a2e1SPrashanth Swaminathan    ~   padding to 16-byte alignment		~ ~
1020*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |
1021*1fd5a2e1SPrashanth Swaminathan    |   NUM_FPR_ARG_REGISTERS slots		| |
1022*1fd5a2e1SPrashanth Swaminathan    |   here fp13 .. fp1		       13*8	| |
1023*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |
1024*1fd5a2e1SPrashanth Swaminathan    |   R3..R10			  8*4/8=32/64	| | NUM_GPR_ARG_REGISTERS
1025*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |
1026*1fd5a2e1SPrashanth Swaminathan    |   TOC=R2 (AIX) Reserved (Darwin)   4/8	| |
1027*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |	stack	|
1028*1fd5a2e1SPrashanth Swaminathan    |   Reserved [compiler,binder]     2*4/8	| |	grows	|
1029*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |	down	V
1030*1fd5a2e1SPrashanth Swaminathan    |   Space for callee's LR		4/8	| |
1031*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |	lower addresses
1032*1fd5a2e1SPrashanth Swaminathan    |   Saved CR [low word for m64]      4/8	| |
1033*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------| |     stack pointer here
1034*1fd5a2e1SPrashanth Swaminathan    |   Current backchain pointer	4/8	|-/	during
1035*1fd5a2e1SPrashanth Swaminathan    |--------------------------------------------|   <<<	ffi_closure_ASM.
1036*1fd5a2e1SPrashanth Swaminathan 
1037*1fd5a2e1SPrashanth Swaminathan */
1038*1fd5a2e1SPrashanth Swaminathan 
1039*1fd5a2e1SPrashanth Swaminathan ffi_status
ffi_prep_closure_loc(ffi_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * codeloc)1040*1fd5a2e1SPrashanth Swaminathan ffi_prep_closure_loc (ffi_closure* closure,
1041*1fd5a2e1SPrashanth Swaminathan 		      ffi_cif* cif,
1042*1fd5a2e1SPrashanth Swaminathan 		      void (*fun)(ffi_cif*, void*, void**, void*),
1043*1fd5a2e1SPrashanth Swaminathan 		      void *user_data,
1044*1fd5a2e1SPrashanth Swaminathan 		      void *codeloc)
1045*1fd5a2e1SPrashanth Swaminathan {
1046*1fd5a2e1SPrashanth Swaminathan   unsigned int *tramp;
1047*1fd5a2e1SPrashanth Swaminathan   struct ffi_aix_trampoline_struct *tramp_aix;
1048*1fd5a2e1SPrashanth Swaminathan   aix_fd *fd;
1049*1fd5a2e1SPrashanth Swaminathan 
1050*1fd5a2e1SPrashanth Swaminathan   switch (cif->abi)
1051*1fd5a2e1SPrashanth Swaminathan     {
1052*1fd5a2e1SPrashanth Swaminathan       case FFI_DARWIN:
1053*1fd5a2e1SPrashanth Swaminathan 
1054*1fd5a2e1SPrashanth Swaminathan 	FFI_ASSERT (cif->abi == FFI_DARWIN);
1055*1fd5a2e1SPrashanth Swaminathan 
1056*1fd5a2e1SPrashanth Swaminathan 	tramp = (unsigned int *) &closure->tramp[0];
1057*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
1058*1fd5a2e1SPrashanth Swaminathan 	tramp[0] = 0x7c0802a6;  /*   mflr    r0  */
1059*1fd5a2e1SPrashanth Swaminathan 	tramp[1] = 0x429f0015;  /*   bcl-    20,4*cr7+so,  +0x18 (L1)  */
1060*1fd5a2e1SPrashanth Swaminathan 	/* We put the addresses here.  */
1061*1fd5a2e1SPrashanth Swaminathan 	tramp[6] = 0x7d6802a6;  /*L1:   mflr    r11  */
1062*1fd5a2e1SPrashanth Swaminathan 	tramp[7] = 0xe98b0000;  /*   ld     r12,0(r11) function address  */
1063*1fd5a2e1SPrashanth Swaminathan 	tramp[8] = 0x7c0803a6;  /*   mtlr    r0   */
1064*1fd5a2e1SPrashanth Swaminathan 	tramp[9] = 0x7d8903a6;  /*   mtctr   r12  */
1065*1fd5a2e1SPrashanth Swaminathan 	tramp[10] = 0xe96b0008;  /*   lwz     r11,8(r11) static chain  */
1066*1fd5a2e1SPrashanth Swaminathan 	tramp[11] = 0x4e800420;  /*   bctr  */
1067*1fd5a2e1SPrashanth Swaminathan 
1068*1fd5a2e1SPrashanth Swaminathan 	*((unsigned long *)&tramp[2]) = (unsigned long) ffi_closure_ASM; /* function  */
1069*1fd5a2e1SPrashanth Swaminathan 	*((unsigned long *)&tramp[4]) = (unsigned long) codeloc; /* context  */
1070*1fd5a2e1SPrashanth Swaminathan #else
1071*1fd5a2e1SPrashanth Swaminathan 	tramp[0] = 0x7c0802a6;  /*   mflr    r0  */
1072*1fd5a2e1SPrashanth Swaminathan 	tramp[1] = 0x429f000d;  /*   bcl-    20,4*cr7+so,0x10  */
1073*1fd5a2e1SPrashanth Swaminathan 	tramp[4] = 0x7d6802a6;  /*   mflr    r11  */
1074*1fd5a2e1SPrashanth Swaminathan 	tramp[5] = 0x818b0000;  /*   lwz     r12,0(r11) function address  */
1075*1fd5a2e1SPrashanth Swaminathan 	tramp[6] = 0x7c0803a6;  /*   mtlr    r0   */
1076*1fd5a2e1SPrashanth Swaminathan 	tramp[7] = 0x7d8903a6;  /*   mtctr   r12  */
1077*1fd5a2e1SPrashanth Swaminathan 	tramp[8] = 0x816b0004;  /*   lwz     r11,4(r11) static chain  */
1078*1fd5a2e1SPrashanth Swaminathan 	tramp[9] = 0x4e800420;  /*   bctr  */
1079*1fd5a2e1SPrashanth Swaminathan 	tramp[2] = (unsigned long) ffi_closure_ASM; /* function  */
1080*1fd5a2e1SPrashanth Swaminathan 	tramp[3] = (unsigned long) codeloc; /* context  */
1081*1fd5a2e1SPrashanth Swaminathan #endif
1082*1fd5a2e1SPrashanth Swaminathan 	closure->cif = cif;
1083*1fd5a2e1SPrashanth Swaminathan 	closure->fun = fun;
1084*1fd5a2e1SPrashanth Swaminathan 	closure->user_data = user_data;
1085*1fd5a2e1SPrashanth Swaminathan 
1086*1fd5a2e1SPrashanth Swaminathan 	/* Flush the icache. Only necessary on Darwin.  */
1087*1fd5a2e1SPrashanth Swaminathan 	flush_range(codeloc, FFI_TRAMPOLINE_SIZE);
1088*1fd5a2e1SPrashanth Swaminathan 
1089*1fd5a2e1SPrashanth Swaminathan 	break;
1090*1fd5a2e1SPrashanth Swaminathan 
1091*1fd5a2e1SPrashanth Swaminathan     case FFI_AIX:
1092*1fd5a2e1SPrashanth Swaminathan 
1093*1fd5a2e1SPrashanth Swaminathan       tramp_aix = (struct ffi_aix_trampoline_struct *) (closure->tramp);
1094*1fd5a2e1SPrashanth Swaminathan       fd = (aix_fd *)(void *)ffi_closure_ASM;
1095*1fd5a2e1SPrashanth Swaminathan 
1096*1fd5a2e1SPrashanth Swaminathan       FFI_ASSERT (cif->abi == FFI_AIX);
1097*1fd5a2e1SPrashanth Swaminathan 
1098*1fd5a2e1SPrashanth Swaminathan       tramp_aix->code_pointer = fd->code_pointer;
1099*1fd5a2e1SPrashanth Swaminathan       tramp_aix->toc = fd->toc;
1100*1fd5a2e1SPrashanth Swaminathan       tramp_aix->static_chain = codeloc;
1101*1fd5a2e1SPrashanth Swaminathan       closure->cif = cif;
1102*1fd5a2e1SPrashanth Swaminathan       closure->fun = fun;
1103*1fd5a2e1SPrashanth Swaminathan       closure->user_data = user_data;
1104*1fd5a2e1SPrashanth Swaminathan       break;
1105*1fd5a2e1SPrashanth Swaminathan 
1106*1fd5a2e1SPrashanth Swaminathan     default:
1107*1fd5a2e1SPrashanth Swaminathan       return FFI_BAD_ABI;
1108*1fd5a2e1SPrashanth Swaminathan       break;
1109*1fd5a2e1SPrashanth Swaminathan     }
1110*1fd5a2e1SPrashanth Swaminathan   return FFI_OK;
1111*1fd5a2e1SPrashanth Swaminathan }
1112*1fd5a2e1SPrashanth Swaminathan 
1113*1fd5a2e1SPrashanth Swaminathan ffi_status
ffi_prep_go_closure(ffi_go_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *))1114*1fd5a2e1SPrashanth Swaminathan ffi_prep_go_closure (ffi_go_closure* closure,
1115*1fd5a2e1SPrashanth Swaminathan 		     ffi_cif* cif,
1116*1fd5a2e1SPrashanth Swaminathan 		     void (*fun)(ffi_cif*, void*, void**, void*))
1117*1fd5a2e1SPrashanth Swaminathan {
1118*1fd5a2e1SPrashanth Swaminathan   switch (cif->abi)
1119*1fd5a2e1SPrashanth Swaminathan     {
1120*1fd5a2e1SPrashanth Swaminathan       case FFI_AIX:
1121*1fd5a2e1SPrashanth Swaminathan 
1122*1fd5a2e1SPrashanth Swaminathan         FFI_ASSERT (cif->abi == FFI_AIX);
1123*1fd5a2e1SPrashanth Swaminathan 
1124*1fd5a2e1SPrashanth Swaminathan         closure->tramp = (void *)ffi_go_closure_ASM;
1125*1fd5a2e1SPrashanth Swaminathan         closure->cif = cif;
1126*1fd5a2e1SPrashanth Swaminathan         closure->fun = fun;
1127*1fd5a2e1SPrashanth Swaminathan         return FFI_OK;
1128*1fd5a2e1SPrashanth Swaminathan 
1129*1fd5a2e1SPrashanth Swaminathan       // For now, ffi_prep_go_closure is only implemented for AIX, not for Darwin
1130*1fd5a2e1SPrashanth Swaminathan       default:
1131*1fd5a2e1SPrashanth Swaminathan         return FFI_BAD_ABI;
1132*1fd5a2e1SPrashanth Swaminathan         break;
1133*1fd5a2e1SPrashanth Swaminathan     }
1134*1fd5a2e1SPrashanth Swaminathan   return FFI_OK;
1135*1fd5a2e1SPrashanth Swaminathan }
1136*1fd5a2e1SPrashanth Swaminathan 
1137*1fd5a2e1SPrashanth Swaminathan static void
flush_icache(char * addr)1138*1fd5a2e1SPrashanth Swaminathan flush_icache(char *addr)
1139*1fd5a2e1SPrashanth Swaminathan {
1140*1fd5a2e1SPrashanth Swaminathan #ifndef _AIX
1141*1fd5a2e1SPrashanth Swaminathan   __asm__ volatile (
1142*1fd5a2e1SPrashanth Swaminathan 		"dcbf 0,%0\n"
1143*1fd5a2e1SPrashanth Swaminathan 		"\tsync\n"
1144*1fd5a2e1SPrashanth Swaminathan 		"\ticbi 0,%0\n"
1145*1fd5a2e1SPrashanth Swaminathan 		"\tsync\n"
1146*1fd5a2e1SPrashanth Swaminathan 		"\tisync"
1147*1fd5a2e1SPrashanth Swaminathan 		: : "r"(addr) : "memory");
1148*1fd5a2e1SPrashanth Swaminathan #endif
1149*1fd5a2e1SPrashanth Swaminathan }
1150*1fd5a2e1SPrashanth Swaminathan 
1151*1fd5a2e1SPrashanth Swaminathan static void
flush_range(char * addr1,int size)1152*1fd5a2e1SPrashanth Swaminathan flush_range(char * addr1, int size)
1153*1fd5a2e1SPrashanth Swaminathan {
1154*1fd5a2e1SPrashanth Swaminathan #define MIN_LINE_SIZE 32
1155*1fd5a2e1SPrashanth Swaminathan   int i;
1156*1fd5a2e1SPrashanth Swaminathan   for (i = 0; i < size; i += MIN_LINE_SIZE)
1157*1fd5a2e1SPrashanth Swaminathan     flush_icache(addr1+i);
1158*1fd5a2e1SPrashanth Swaminathan   flush_icache(addr1+size-1);
1159*1fd5a2e1SPrashanth Swaminathan }
1160*1fd5a2e1SPrashanth Swaminathan 
1161*1fd5a2e1SPrashanth Swaminathan typedef union
1162*1fd5a2e1SPrashanth Swaminathan {
1163*1fd5a2e1SPrashanth Swaminathan   float f;
1164*1fd5a2e1SPrashanth Swaminathan   double d;
1165*1fd5a2e1SPrashanth Swaminathan } ffi_dblfl;
1166*1fd5a2e1SPrashanth Swaminathan 
1167*1fd5a2e1SPrashanth Swaminathan ffi_type *
1168*1fd5a2e1SPrashanth Swaminathan ffi_closure_helper_DARWIN (ffi_closure *, void *,
1169*1fd5a2e1SPrashanth Swaminathan 			   unsigned long *, ffi_dblfl *);
1170*1fd5a2e1SPrashanth Swaminathan 
1171*1fd5a2e1SPrashanth Swaminathan ffi_type *
1172*1fd5a2e1SPrashanth Swaminathan ffi_go_closure_helper_DARWIN (ffi_go_closure*, void *,
1173*1fd5a2e1SPrashanth Swaminathan 			      unsigned long *, ffi_dblfl *);
1174*1fd5a2e1SPrashanth Swaminathan 
1175*1fd5a2e1SPrashanth Swaminathan /* Basically the trampoline invokes ffi_closure_ASM, and on
1176*1fd5a2e1SPrashanth Swaminathan    entry, r11 holds the address of the closure.
1177*1fd5a2e1SPrashanth Swaminathan    After storing the registers that could possibly contain
1178*1fd5a2e1SPrashanth Swaminathan    parameters to be passed into the stack frame and setting
1179*1fd5a2e1SPrashanth Swaminathan    up space for a return value, ffi_closure_ASM invokes the
1180*1fd5a2e1SPrashanth Swaminathan    following helper function to do most of the work.  */
1181*1fd5a2e1SPrashanth Swaminathan 
1182*1fd5a2e1SPrashanth Swaminathan static ffi_type *
ffi_closure_helper_common(ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * rvalue,unsigned long * pgr,ffi_dblfl * pfr)1183*1fd5a2e1SPrashanth Swaminathan ffi_closure_helper_common (ffi_cif* cif,
1184*1fd5a2e1SPrashanth Swaminathan 			   void (*fun)(ffi_cif*, void*, void**, void*),
1185*1fd5a2e1SPrashanth Swaminathan 			   void *user_data, void *rvalue,
1186*1fd5a2e1SPrashanth Swaminathan 			   unsigned long *pgr, ffi_dblfl *pfr)
1187*1fd5a2e1SPrashanth Swaminathan {
1188*1fd5a2e1SPrashanth Swaminathan   /* rvalue is the pointer to space for return value in closure assembly
1189*1fd5a2e1SPrashanth Swaminathan      pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM
1190*1fd5a2e1SPrashanth Swaminathan      pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM.  */
1191*1fd5a2e1SPrashanth Swaminathan 
1192*1fd5a2e1SPrashanth Swaminathan   typedef double ldbits[2];
1193*1fd5a2e1SPrashanth Swaminathan 
1194*1fd5a2e1SPrashanth Swaminathan   union ldu
1195*1fd5a2e1SPrashanth Swaminathan   {
1196*1fd5a2e1SPrashanth Swaminathan     ldbits lb;
1197*1fd5a2e1SPrashanth Swaminathan     long double ld;
1198*1fd5a2e1SPrashanth Swaminathan   };
1199*1fd5a2e1SPrashanth Swaminathan 
1200*1fd5a2e1SPrashanth Swaminathan   void **          avalue;
1201*1fd5a2e1SPrashanth Swaminathan   ffi_type **      arg_types;
1202*1fd5a2e1SPrashanth Swaminathan   long             i, avn;
1203*1fd5a2e1SPrashanth Swaminathan   ffi_dblfl *      end_pfr = pfr + NUM_FPR_ARG_REGISTERS;
1204*1fd5a2e1SPrashanth Swaminathan   unsigned         size_al;
1205*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
1206*1fd5a2e1SPrashanth Swaminathan   unsigned 	   fpsused = 0;
1207*1fd5a2e1SPrashanth Swaminathan #endif
1208*1fd5a2e1SPrashanth Swaminathan 
1209*1fd5a2e1SPrashanth Swaminathan   avalue = alloca (cif->nargs * sizeof(void *));
1210*1fd5a2e1SPrashanth Swaminathan 
1211*1fd5a2e1SPrashanth Swaminathan   if (cif->rtype->type == FFI_TYPE_STRUCT)
1212*1fd5a2e1SPrashanth Swaminathan     {
1213*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
1214*1fd5a2e1SPrashanth Swaminathan       if (!darwin64_struct_ret_by_value_p (cif->rtype))
1215*1fd5a2e1SPrashanth Swaminathan 	{
1216*1fd5a2e1SPrashanth Swaminathan     	  /* Won't fit into the regs - return by ref.  */
1217*1fd5a2e1SPrashanth Swaminathan 	  rvalue = (void *) *pgr;
1218*1fd5a2e1SPrashanth Swaminathan 	  pgr++;
1219*1fd5a2e1SPrashanth Swaminathan 	}
1220*1fd5a2e1SPrashanth Swaminathan #elif defined(DARWIN_PPC)
1221*1fd5a2e1SPrashanth Swaminathan       if (cif->rtype->size > 4)
1222*1fd5a2e1SPrashanth Swaminathan 	{
1223*1fd5a2e1SPrashanth Swaminathan 	  rvalue = (void *) *pgr;
1224*1fd5a2e1SPrashanth Swaminathan 	  pgr++;
1225*1fd5a2e1SPrashanth Swaminathan 	}
1226*1fd5a2e1SPrashanth Swaminathan #else /* assume we return by ref.  */
1227*1fd5a2e1SPrashanth Swaminathan       rvalue = (void *) *pgr;
1228*1fd5a2e1SPrashanth Swaminathan       pgr++;
1229*1fd5a2e1SPrashanth Swaminathan #endif
1230*1fd5a2e1SPrashanth Swaminathan     }
1231*1fd5a2e1SPrashanth Swaminathan 
1232*1fd5a2e1SPrashanth Swaminathan   i = 0;
1233*1fd5a2e1SPrashanth Swaminathan   avn = cif->nargs;
1234*1fd5a2e1SPrashanth Swaminathan   arg_types = cif->arg_types;
1235*1fd5a2e1SPrashanth Swaminathan 
1236*1fd5a2e1SPrashanth Swaminathan   /* Grab the addresses of the arguments from the stack frame.  */
1237*1fd5a2e1SPrashanth Swaminathan   while (i < avn)
1238*1fd5a2e1SPrashanth Swaminathan     {
1239*1fd5a2e1SPrashanth Swaminathan       switch (arg_types[i]->type)
1240*1fd5a2e1SPrashanth Swaminathan 	{
1241*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT8:
1242*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT8:
1243*1fd5a2e1SPrashanth Swaminathan #if  defined(POWERPC64)
1244*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = (char *) pgr + 7;
1245*1fd5a2e1SPrashanth Swaminathan #else
1246*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = (char *) pgr + 3;
1247*1fd5a2e1SPrashanth Swaminathan #endif
1248*1fd5a2e1SPrashanth Swaminathan 	  pgr++;
1249*1fd5a2e1SPrashanth Swaminathan 	  break;
1250*1fd5a2e1SPrashanth Swaminathan 
1251*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT16:
1252*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT16:
1253*1fd5a2e1SPrashanth Swaminathan #if  defined(POWERPC64)
1254*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = (char *) pgr + 6;
1255*1fd5a2e1SPrashanth Swaminathan #else
1256*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = (char *) pgr + 2;
1257*1fd5a2e1SPrashanth Swaminathan #endif
1258*1fd5a2e1SPrashanth Swaminathan 	  pgr++;
1259*1fd5a2e1SPrashanth Swaminathan 	  break;
1260*1fd5a2e1SPrashanth Swaminathan 
1261*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT32:
1262*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT32:
1263*1fd5a2e1SPrashanth Swaminathan #if  defined(POWERPC64)
1264*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = (char *) pgr + 4;
1265*1fd5a2e1SPrashanth Swaminathan #else
1266*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_POINTER:
1267*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = pgr;
1268*1fd5a2e1SPrashanth Swaminathan #endif
1269*1fd5a2e1SPrashanth Swaminathan 	  pgr++;
1270*1fd5a2e1SPrashanth Swaminathan 	  break;
1271*1fd5a2e1SPrashanth Swaminathan 
1272*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_STRUCT:
1273*1fd5a2e1SPrashanth Swaminathan 	  size_al = arg_types[i]->size;
1274*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
1275*1fd5a2e1SPrashanth Swaminathan 	  pgr = (unsigned long *)FFI_ALIGN((char *)pgr, arg_types[i]->alignment);
1276*1fd5a2e1SPrashanth Swaminathan 	  if (size_al < 3 || size_al == 4)
1277*1fd5a2e1SPrashanth Swaminathan 	    {
1278*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = ((char *)pgr)+8-size_al;
1279*1fd5a2e1SPrashanth Swaminathan 	      if (arg_types[i]->elements[0]->type == FFI_TYPE_FLOAT
1280*1fd5a2e1SPrashanth Swaminathan 		  && fpsused < NUM_FPR_ARG_REGISTERS)
1281*1fd5a2e1SPrashanth Swaminathan 		{
1282*1fd5a2e1SPrashanth Swaminathan 		  *(float *)pgr = (float) *(double *)pfr;
1283*1fd5a2e1SPrashanth Swaminathan 		  pfr++;
1284*1fd5a2e1SPrashanth Swaminathan 		  fpsused++;
1285*1fd5a2e1SPrashanth Swaminathan 		}
1286*1fd5a2e1SPrashanth Swaminathan 	    }
1287*1fd5a2e1SPrashanth Swaminathan 	  else
1288*1fd5a2e1SPrashanth Swaminathan 	    {
1289*1fd5a2e1SPrashanth Swaminathan 	      if (size_al != 16)
1290*1fd5a2e1SPrashanth Swaminathan 		pfr = (ffi_dblfl *)
1291*1fd5a2e1SPrashanth Swaminathan 		    darwin64_struct_floats_to_mem (arg_types[i], (char *)pgr,
1292*1fd5a2e1SPrashanth Swaminathan 						   (double *)pfr, &fpsused);
1293*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = pgr;
1294*1fd5a2e1SPrashanth Swaminathan 	    }
1295*1fd5a2e1SPrashanth Swaminathan 	  pgr += (size_al + 7) / 8;
1296*1fd5a2e1SPrashanth Swaminathan #else
1297*1fd5a2e1SPrashanth Swaminathan 	  /* If the first member of the struct is a double, then align
1298*1fd5a2e1SPrashanth Swaminathan 	     the struct to double-word.  */
1299*1fd5a2e1SPrashanth Swaminathan 	  if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE)
1300*1fd5a2e1SPrashanth Swaminathan 	    size_al = FFI_ALIGN(arg_types[i]->size, 8);
1301*1fd5a2e1SPrashanth Swaminathan #  if defined(POWERPC64)
1302*1fd5a2e1SPrashanth Swaminathan 	  FFI_ASSERT (cif->abi != FFI_DARWIN);
1303*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = pgr;
1304*1fd5a2e1SPrashanth Swaminathan 	  pgr += (size_al + 7) / 8;
1305*1fd5a2e1SPrashanth Swaminathan #  else
1306*1fd5a2e1SPrashanth Swaminathan 	  /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
1307*1fd5a2e1SPrashanth Swaminathan 	     SI 4 bytes) are aligned as if they were those modes.  */
1308*1fd5a2e1SPrashanth Swaminathan 	  if (size_al < 3 && cif->abi == FFI_DARWIN)
1309*1fd5a2e1SPrashanth Swaminathan 	    avalue[i] = (char*) pgr + 4 - size_al;
1310*1fd5a2e1SPrashanth Swaminathan 	  else
1311*1fd5a2e1SPrashanth Swaminathan 	    avalue[i] = pgr;
1312*1fd5a2e1SPrashanth Swaminathan 	  pgr += (size_al + 3) / 4;
1313*1fd5a2e1SPrashanth Swaminathan #  endif
1314*1fd5a2e1SPrashanth Swaminathan #endif
1315*1fd5a2e1SPrashanth Swaminathan 	  break;
1316*1fd5a2e1SPrashanth Swaminathan 
1317*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT64:
1318*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT64:
1319*1fd5a2e1SPrashanth Swaminathan #if  defined(POWERPC64)
1320*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_POINTER:
1321*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = pgr;
1322*1fd5a2e1SPrashanth Swaminathan 	  pgr++;
1323*1fd5a2e1SPrashanth Swaminathan 	  break;
1324*1fd5a2e1SPrashanth Swaminathan #else
1325*1fd5a2e1SPrashanth Swaminathan 	  /* Long long ints are passed in two gpr's.  */
1326*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = pgr;
1327*1fd5a2e1SPrashanth Swaminathan 	  pgr += 2;
1328*1fd5a2e1SPrashanth Swaminathan 	  break;
1329*1fd5a2e1SPrashanth Swaminathan #endif
1330*1fd5a2e1SPrashanth Swaminathan 
1331*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_FLOAT:
1332*1fd5a2e1SPrashanth Swaminathan 	  /* A float value consumes a GPR.
1333*1fd5a2e1SPrashanth Swaminathan 	     There are 13 64bit floating point registers.  */
1334*1fd5a2e1SPrashanth Swaminathan 	  if (pfr < end_pfr)
1335*1fd5a2e1SPrashanth Swaminathan 	    {
1336*1fd5a2e1SPrashanth Swaminathan 	      double temp = pfr->d;
1337*1fd5a2e1SPrashanth Swaminathan 	      pfr->f = (float) temp;
1338*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = pfr;
1339*1fd5a2e1SPrashanth Swaminathan 	      pfr++;
1340*1fd5a2e1SPrashanth Swaminathan 	    }
1341*1fd5a2e1SPrashanth Swaminathan 	  else
1342*1fd5a2e1SPrashanth Swaminathan 	    {
1343*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = pgr;
1344*1fd5a2e1SPrashanth Swaminathan 	    }
1345*1fd5a2e1SPrashanth Swaminathan 	  pgr++;
1346*1fd5a2e1SPrashanth Swaminathan 	  break;
1347*1fd5a2e1SPrashanth Swaminathan 
1348*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_DOUBLE:
1349*1fd5a2e1SPrashanth Swaminathan 	  /* A double value consumes two GPRs.
1350*1fd5a2e1SPrashanth Swaminathan 	     There are 13 64bit floating point registers.  */
1351*1fd5a2e1SPrashanth Swaminathan 	  if (pfr < end_pfr)
1352*1fd5a2e1SPrashanth Swaminathan 	    {
1353*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = pfr;
1354*1fd5a2e1SPrashanth Swaminathan 	      pfr++;
1355*1fd5a2e1SPrashanth Swaminathan 	    }
1356*1fd5a2e1SPrashanth Swaminathan 	  else
1357*1fd5a2e1SPrashanth Swaminathan 	    {
1358*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = pgr;
1359*1fd5a2e1SPrashanth Swaminathan 	    }
1360*1fd5a2e1SPrashanth Swaminathan #ifdef POWERPC64
1361*1fd5a2e1SPrashanth Swaminathan 	  pgr++;
1362*1fd5a2e1SPrashanth Swaminathan #else
1363*1fd5a2e1SPrashanth Swaminathan 	  pgr += 2;
1364*1fd5a2e1SPrashanth Swaminathan #endif
1365*1fd5a2e1SPrashanth Swaminathan 	  break;
1366*1fd5a2e1SPrashanth Swaminathan 
1367*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1368*1fd5a2e1SPrashanth Swaminathan 
1369*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_LONGDOUBLE:
1370*1fd5a2e1SPrashanth Swaminathan #ifdef POWERPC64
1371*1fd5a2e1SPrashanth Swaminathan 	  if (pfr + 1 < end_pfr)
1372*1fd5a2e1SPrashanth Swaminathan 	    {
1373*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = pfr;
1374*1fd5a2e1SPrashanth Swaminathan 	      pfr += 2;
1375*1fd5a2e1SPrashanth Swaminathan 	    }
1376*1fd5a2e1SPrashanth Swaminathan 	  else
1377*1fd5a2e1SPrashanth Swaminathan 	    {
1378*1fd5a2e1SPrashanth Swaminathan 	      if (pfr < end_pfr)
1379*1fd5a2e1SPrashanth Swaminathan 		{
1380*1fd5a2e1SPrashanth Swaminathan 		  *pgr = *(unsigned long *) pfr;
1381*1fd5a2e1SPrashanth Swaminathan 		  pfr++;
1382*1fd5a2e1SPrashanth Swaminathan 		}
1383*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = pgr;
1384*1fd5a2e1SPrashanth Swaminathan 	    }
1385*1fd5a2e1SPrashanth Swaminathan 	  pgr += 2;
1386*1fd5a2e1SPrashanth Swaminathan #else  /* POWERPC64 */
1387*1fd5a2e1SPrashanth Swaminathan 	  /* A long double value consumes four GPRs and two FPRs.
1388*1fd5a2e1SPrashanth Swaminathan 	     There are 13 64bit floating point registers.  */
1389*1fd5a2e1SPrashanth Swaminathan 	  if (pfr + 1 < end_pfr)
1390*1fd5a2e1SPrashanth Swaminathan 	    {
1391*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = pfr;
1392*1fd5a2e1SPrashanth Swaminathan 	      pfr += 2;
1393*1fd5a2e1SPrashanth Swaminathan 	    }
1394*1fd5a2e1SPrashanth Swaminathan 	  /* Here we have the situation where one part of the long double
1395*1fd5a2e1SPrashanth Swaminathan 	     is stored in fpr13 and the other part is already on the stack.
1396*1fd5a2e1SPrashanth Swaminathan 	     We use a union to pass the long double to avalue[i].  */
1397*1fd5a2e1SPrashanth Swaminathan 	  else if (pfr + 1 == end_pfr)
1398*1fd5a2e1SPrashanth Swaminathan 	    {
1399*1fd5a2e1SPrashanth Swaminathan 	      union ldu temp_ld;
1400*1fd5a2e1SPrashanth Swaminathan 	      memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits));
1401*1fd5a2e1SPrashanth Swaminathan 	      memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits));
1402*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = &temp_ld.ld;
1403*1fd5a2e1SPrashanth Swaminathan 	      pfr++;
1404*1fd5a2e1SPrashanth Swaminathan 	    }
1405*1fd5a2e1SPrashanth Swaminathan 	  else
1406*1fd5a2e1SPrashanth Swaminathan 	    {
1407*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = pgr;
1408*1fd5a2e1SPrashanth Swaminathan 	    }
1409*1fd5a2e1SPrashanth Swaminathan 	  pgr += 4;
1410*1fd5a2e1SPrashanth Swaminathan #endif  /* POWERPC64 */
1411*1fd5a2e1SPrashanth Swaminathan 	  break;
1412*1fd5a2e1SPrashanth Swaminathan #endif
1413*1fd5a2e1SPrashanth Swaminathan 	default:
1414*1fd5a2e1SPrashanth Swaminathan 	  FFI_ASSERT(0);
1415*1fd5a2e1SPrashanth Swaminathan 	}
1416*1fd5a2e1SPrashanth Swaminathan       i++;
1417*1fd5a2e1SPrashanth Swaminathan     }
1418*1fd5a2e1SPrashanth Swaminathan 
1419*1fd5a2e1SPrashanth Swaminathan   (fun) (cif, rvalue, avalue, user_data);
1420*1fd5a2e1SPrashanth Swaminathan 
1421*1fd5a2e1SPrashanth Swaminathan   /* Tell ffi_closure_ASM to perform return type promotions.  */
1422*1fd5a2e1SPrashanth Swaminathan   return cif->rtype;
1423*1fd5a2e1SPrashanth Swaminathan }
1424*1fd5a2e1SPrashanth Swaminathan 
1425*1fd5a2e1SPrashanth Swaminathan ffi_type *
ffi_closure_helper_DARWIN(ffi_closure * closure,void * rvalue,unsigned long * pgr,ffi_dblfl * pfr)1426*1fd5a2e1SPrashanth Swaminathan ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue,
1427*1fd5a2e1SPrashanth Swaminathan 			   unsigned long *pgr, ffi_dblfl *pfr)
1428*1fd5a2e1SPrashanth Swaminathan {
1429*1fd5a2e1SPrashanth Swaminathan   return ffi_closure_helper_common (closure->cif, closure->fun,
1430*1fd5a2e1SPrashanth Swaminathan 				    closure->user_data, rvalue, pgr, pfr);
1431*1fd5a2e1SPrashanth Swaminathan }
1432*1fd5a2e1SPrashanth Swaminathan 
1433*1fd5a2e1SPrashanth Swaminathan ffi_type *
ffi_go_closure_helper_DARWIN(ffi_go_closure * closure,void * rvalue,unsigned long * pgr,ffi_dblfl * pfr)1434*1fd5a2e1SPrashanth Swaminathan ffi_go_closure_helper_DARWIN (ffi_go_closure *closure, void *rvalue,
1435*1fd5a2e1SPrashanth Swaminathan 			      unsigned long *pgr, ffi_dblfl *pfr)
1436*1fd5a2e1SPrashanth Swaminathan {
1437*1fd5a2e1SPrashanth Swaminathan   return ffi_closure_helper_common (closure->cif, closure->fun,
1438*1fd5a2e1SPrashanth Swaminathan 				    closure, rvalue, pgr, pfr);
1439*1fd5a2e1SPrashanth Swaminathan }
1440*1fd5a2e1SPrashanth Swaminathan 
1441