1*1fd5a2e1SPrashanth Swaminathan /* -----------------------------------------------------------------------
2*1fd5a2e1SPrashanth Swaminathan ffi.c - Copyright (c) 1998, 2007, 2008, 2012 Red Hat, Inc.
3*1fd5a2e1SPrashanth Swaminathan Copyright (c) 2000 Hewlett Packard Company
4*1fd5a2e1SPrashanth Swaminathan Copyright (c) 2011 Anthony Green
5*1fd5a2e1SPrashanth Swaminathan
6*1fd5a2e1SPrashanth Swaminathan IA64 Foreign Function Interface
7*1fd5a2e1SPrashanth Swaminathan
8*1fd5a2e1SPrashanth Swaminathan Permission is hereby granted, free of charge, to any person obtaining
9*1fd5a2e1SPrashanth Swaminathan a copy of this software and associated documentation files (the
10*1fd5a2e1SPrashanth Swaminathan ``Software''), to deal in the Software without restriction, including
11*1fd5a2e1SPrashanth Swaminathan without limitation the rights to use, copy, modify, merge, publish,
12*1fd5a2e1SPrashanth Swaminathan distribute, sublicense, and/or sell copies of the Software, and to
13*1fd5a2e1SPrashanth Swaminathan permit persons to whom the Software is furnished to do so, subject to
14*1fd5a2e1SPrashanth Swaminathan the following conditions:
15*1fd5a2e1SPrashanth Swaminathan
16*1fd5a2e1SPrashanth Swaminathan The above copyright notice and this permission notice shall be included
17*1fd5a2e1SPrashanth Swaminathan in all copies or substantial portions of the Software.
18*1fd5a2e1SPrashanth Swaminathan
19*1fd5a2e1SPrashanth Swaminathan THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
20*1fd5a2e1SPrashanth Swaminathan EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21*1fd5a2e1SPrashanth Swaminathan MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22*1fd5a2e1SPrashanth Swaminathan NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23*1fd5a2e1SPrashanth Swaminathan HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24*1fd5a2e1SPrashanth Swaminathan WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25*1fd5a2e1SPrashanth Swaminathan OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26*1fd5a2e1SPrashanth Swaminathan DEALINGS IN THE SOFTWARE.
27*1fd5a2e1SPrashanth Swaminathan ----------------------------------------------------------------------- */
28*1fd5a2e1SPrashanth Swaminathan
29*1fd5a2e1SPrashanth Swaminathan #include <ffi.h>
30*1fd5a2e1SPrashanth Swaminathan #include <ffi_common.h>
31*1fd5a2e1SPrashanth Swaminathan
32*1fd5a2e1SPrashanth Swaminathan #include <stdlib.h>
33*1fd5a2e1SPrashanth Swaminathan #include <stdbool.h>
34*1fd5a2e1SPrashanth Swaminathan #include <float.h>
35*1fd5a2e1SPrashanth Swaminathan
36*1fd5a2e1SPrashanth Swaminathan #include "ia64_flags.h"
37*1fd5a2e1SPrashanth Swaminathan
38*1fd5a2e1SPrashanth Swaminathan /* A 64-bit pointer value. In LP64 mode, this is effectively a plain
39*1fd5a2e1SPrashanth Swaminathan pointer. In ILP32 mode, it's a pointer that's been extended to
40*1fd5a2e1SPrashanth Swaminathan 64 bits by "addp4". */
41*1fd5a2e1SPrashanth Swaminathan typedef void *PTR64 __attribute__((mode(DI)));
42*1fd5a2e1SPrashanth Swaminathan
43*1fd5a2e1SPrashanth Swaminathan /* Memory image of fp register contents. This is the implementation
44*1fd5a2e1SPrashanth Swaminathan specific format used by ldf.fill/stf.spill. All we care about is
45*1fd5a2e1SPrashanth Swaminathan that it wants a 16 byte aligned slot. */
46*1fd5a2e1SPrashanth Swaminathan typedef struct
47*1fd5a2e1SPrashanth Swaminathan {
48*1fd5a2e1SPrashanth Swaminathan UINT64 x[2] __attribute__((aligned(16)));
49*1fd5a2e1SPrashanth Swaminathan } fpreg;
50*1fd5a2e1SPrashanth Swaminathan
51*1fd5a2e1SPrashanth Swaminathan
52*1fd5a2e1SPrashanth Swaminathan /* The stack layout given to ffi_call_unix and ffi_closure_unix_inner. */
53*1fd5a2e1SPrashanth Swaminathan
54*1fd5a2e1SPrashanth Swaminathan struct ia64_args
55*1fd5a2e1SPrashanth Swaminathan {
56*1fd5a2e1SPrashanth Swaminathan fpreg fp_regs[8]; /* Contents of 8 fp arg registers. */
57*1fd5a2e1SPrashanth Swaminathan UINT64 gp_regs[8]; /* Contents of 8 gp arg registers. */
58*1fd5a2e1SPrashanth Swaminathan UINT64 other_args[]; /* Arguments passed on stack, variable size. */
59*1fd5a2e1SPrashanth Swaminathan };
60*1fd5a2e1SPrashanth Swaminathan
61*1fd5a2e1SPrashanth Swaminathan
62*1fd5a2e1SPrashanth Swaminathan /* Adjust ADDR, a pointer to an 8 byte slot, to point to the low LEN bytes. */
63*1fd5a2e1SPrashanth Swaminathan
64*1fd5a2e1SPrashanth Swaminathan static inline void *
endian_adjust(void * addr,size_t len)65*1fd5a2e1SPrashanth Swaminathan endian_adjust (void *addr, size_t len)
66*1fd5a2e1SPrashanth Swaminathan {
67*1fd5a2e1SPrashanth Swaminathan #ifdef __BIG_ENDIAN__
68*1fd5a2e1SPrashanth Swaminathan return addr + (8 - len);
69*1fd5a2e1SPrashanth Swaminathan #else
70*1fd5a2e1SPrashanth Swaminathan return addr;
71*1fd5a2e1SPrashanth Swaminathan #endif
72*1fd5a2e1SPrashanth Swaminathan }
73*1fd5a2e1SPrashanth Swaminathan
74*1fd5a2e1SPrashanth Swaminathan /* Store VALUE to ADDR in the current cpu implementation's fp spill format.
75*1fd5a2e1SPrashanth Swaminathan This is a macro instead of a function, so that it works for all 3 floating
76*1fd5a2e1SPrashanth Swaminathan point types without type conversions. Type conversion to long double breaks
77*1fd5a2e1SPrashanth Swaminathan the denorm support. */
78*1fd5a2e1SPrashanth Swaminathan
79*1fd5a2e1SPrashanth Swaminathan #define stf_spill(addr, value) \
80*1fd5a2e1SPrashanth Swaminathan asm ("stf.spill %0 = %1%P0" : "=m" (*addr) : "f"(value));
81*1fd5a2e1SPrashanth Swaminathan
82*1fd5a2e1SPrashanth Swaminathan /* Load a value from ADDR, which is in the current cpu implementation's
83*1fd5a2e1SPrashanth Swaminathan fp spill format. As above, this must also be a macro. */
84*1fd5a2e1SPrashanth Swaminathan
85*1fd5a2e1SPrashanth Swaminathan #define ldf_fill(result, addr) \
86*1fd5a2e1SPrashanth Swaminathan asm ("ldf.fill %0 = %1%P1" : "=f"(result) : "m"(*addr));
87*1fd5a2e1SPrashanth Swaminathan
88*1fd5a2e1SPrashanth Swaminathan /* Return the size of the C type associated with with TYPE. Which will
89*1fd5a2e1SPrashanth Swaminathan be one of the FFI_IA64_TYPE_HFA_* values. */
90*1fd5a2e1SPrashanth Swaminathan
91*1fd5a2e1SPrashanth Swaminathan static size_t
hfa_type_size(int type)92*1fd5a2e1SPrashanth Swaminathan hfa_type_size (int type)
93*1fd5a2e1SPrashanth Swaminathan {
94*1fd5a2e1SPrashanth Swaminathan switch (type)
95*1fd5a2e1SPrashanth Swaminathan {
96*1fd5a2e1SPrashanth Swaminathan case FFI_IA64_TYPE_HFA_FLOAT:
97*1fd5a2e1SPrashanth Swaminathan return sizeof(float);
98*1fd5a2e1SPrashanth Swaminathan case FFI_IA64_TYPE_HFA_DOUBLE:
99*1fd5a2e1SPrashanth Swaminathan return sizeof(double);
100*1fd5a2e1SPrashanth Swaminathan case FFI_IA64_TYPE_HFA_LDOUBLE:
101*1fd5a2e1SPrashanth Swaminathan return sizeof(__float80);
102*1fd5a2e1SPrashanth Swaminathan default:
103*1fd5a2e1SPrashanth Swaminathan abort ();
104*1fd5a2e1SPrashanth Swaminathan }
105*1fd5a2e1SPrashanth Swaminathan }
106*1fd5a2e1SPrashanth Swaminathan
107*1fd5a2e1SPrashanth Swaminathan /* Load from ADDR a value indicated by TYPE. Which will be one of
108*1fd5a2e1SPrashanth Swaminathan the FFI_IA64_TYPE_HFA_* values. */
109*1fd5a2e1SPrashanth Swaminathan
110*1fd5a2e1SPrashanth Swaminathan static void
hfa_type_load(fpreg * fpaddr,int type,void * addr)111*1fd5a2e1SPrashanth Swaminathan hfa_type_load (fpreg *fpaddr, int type, void *addr)
112*1fd5a2e1SPrashanth Swaminathan {
113*1fd5a2e1SPrashanth Swaminathan switch (type)
114*1fd5a2e1SPrashanth Swaminathan {
115*1fd5a2e1SPrashanth Swaminathan case FFI_IA64_TYPE_HFA_FLOAT:
116*1fd5a2e1SPrashanth Swaminathan stf_spill (fpaddr, *(float *) addr);
117*1fd5a2e1SPrashanth Swaminathan return;
118*1fd5a2e1SPrashanth Swaminathan case FFI_IA64_TYPE_HFA_DOUBLE:
119*1fd5a2e1SPrashanth Swaminathan stf_spill (fpaddr, *(double *) addr);
120*1fd5a2e1SPrashanth Swaminathan return;
121*1fd5a2e1SPrashanth Swaminathan case FFI_IA64_TYPE_HFA_LDOUBLE:
122*1fd5a2e1SPrashanth Swaminathan stf_spill (fpaddr, *(__float80 *) addr);
123*1fd5a2e1SPrashanth Swaminathan return;
124*1fd5a2e1SPrashanth Swaminathan default:
125*1fd5a2e1SPrashanth Swaminathan abort ();
126*1fd5a2e1SPrashanth Swaminathan }
127*1fd5a2e1SPrashanth Swaminathan }
128*1fd5a2e1SPrashanth Swaminathan
129*1fd5a2e1SPrashanth Swaminathan /* Load VALUE into ADDR as indicated by TYPE. Which will be one of
130*1fd5a2e1SPrashanth Swaminathan the FFI_IA64_TYPE_HFA_* values. */
131*1fd5a2e1SPrashanth Swaminathan
132*1fd5a2e1SPrashanth Swaminathan static void
hfa_type_store(int type,void * addr,fpreg * fpaddr)133*1fd5a2e1SPrashanth Swaminathan hfa_type_store (int type, void *addr, fpreg *fpaddr)
134*1fd5a2e1SPrashanth Swaminathan {
135*1fd5a2e1SPrashanth Swaminathan switch (type)
136*1fd5a2e1SPrashanth Swaminathan {
137*1fd5a2e1SPrashanth Swaminathan case FFI_IA64_TYPE_HFA_FLOAT:
138*1fd5a2e1SPrashanth Swaminathan {
139*1fd5a2e1SPrashanth Swaminathan float result;
140*1fd5a2e1SPrashanth Swaminathan ldf_fill (result, fpaddr);
141*1fd5a2e1SPrashanth Swaminathan *(float *) addr = result;
142*1fd5a2e1SPrashanth Swaminathan break;
143*1fd5a2e1SPrashanth Swaminathan }
144*1fd5a2e1SPrashanth Swaminathan case FFI_IA64_TYPE_HFA_DOUBLE:
145*1fd5a2e1SPrashanth Swaminathan {
146*1fd5a2e1SPrashanth Swaminathan double result;
147*1fd5a2e1SPrashanth Swaminathan ldf_fill (result, fpaddr);
148*1fd5a2e1SPrashanth Swaminathan *(double *) addr = result;
149*1fd5a2e1SPrashanth Swaminathan break;
150*1fd5a2e1SPrashanth Swaminathan }
151*1fd5a2e1SPrashanth Swaminathan case FFI_IA64_TYPE_HFA_LDOUBLE:
152*1fd5a2e1SPrashanth Swaminathan {
153*1fd5a2e1SPrashanth Swaminathan __float80 result;
154*1fd5a2e1SPrashanth Swaminathan ldf_fill (result, fpaddr);
155*1fd5a2e1SPrashanth Swaminathan *(__float80 *) addr = result;
156*1fd5a2e1SPrashanth Swaminathan break;
157*1fd5a2e1SPrashanth Swaminathan }
158*1fd5a2e1SPrashanth Swaminathan default:
159*1fd5a2e1SPrashanth Swaminathan abort ();
160*1fd5a2e1SPrashanth Swaminathan }
161*1fd5a2e1SPrashanth Swaminathan }
162*1fd5a2e1SPrashanth Swaminathan
163*1fd5a2e1SPrashanth Swaminathan /* Is TYPE a struct containing floats, doubles, or extended doubles,
164*1fd5a2e1SPrashanth Swaminathan all of the same fp type? If so, return the element type. Return
165*1fd5a2e1SPrashanth Swaminathan FFI_TYPE_VOID if not. */
166*1fd5a2e1SPrashanth Swaminathan
167*1fd5a2e1SPrashanth Swaminathan static int
hfa_element_type(ffi_type * type,int nested)168*1fd5a2e1SPrashanth Swaminathan hfa_element_type (ffi_type *type, int nested)
169*1fd5a2e1SPrashanth Swaminathan {
170*1fd5a2e1SPrashanth Swaminathan int element = FFI_TYPE_VOID;
171*1fd5a2e1SPrashanth Swaminathan
172*1fd5a2e1SPrashanth Swaminathan switch (type->type)
173*1fd5a2e1SPrashanth Swaminathan {
174*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
175*1fd5a2e1SPrashanth Swaminathan /* We want to return VOID for raw floating-point types, but the
176*1fd5a2e1SPrashanth Swaminathan synthetic HFA type if we're nested within an aggregate. */
177*1fd5a2e1SPrashanth Swaminathan if (nested)
178*1fd5a2e1SPrashanth Swaminathan element = FFI_IA64_TYPE_HFA_FLOAT;
179*1fd5a2e1SPrashanth Swaminathan break;
180*1fd5a2e1SPrashanth Swaminathan
181*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
182*1fd5a2e1SPrashanth Swaminathan /* Similarly. */
183*1fd5a2e1SPrashanth Swaminathan if (nested)
184*1fd5a2e1SPrashanth Swaminathan element = FFI_IA64_TYPE_HFA_DOUBLE;
185*1fd5a2e1SPrashanth Swaminathan break;
186*1fd5a2e1SPrashanth Swaminathan
187*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
188*1fd5a2e1SPrashanth Swaminathan /* Similarly, except that that HFA is true for double extended,
189*1fd5a2e1SPrashanth Swaminathan but not quad precision. Both have sizeof == 16, so tell the
190*1fd5a2e1SPrashanth Swaminathan difference based on the precision. */
191*1fd5a2e1SPrashanth Swaminathan if (LDBL_MANT_DIG == 64 && nested)
192*1fd5a2e1SPrashanth Swaminathan element = FFI_IA64_TYPE_HFA_LDOUBLE;
193*1fd5a2e1SPrashanth Swaminathan break;
194*1fd5a2e1SPrashanth Swaminathan
195*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
196*1fd5a2e1SPrashanth Swaminathan {
197*1fd5a2e1SPrashanth Swaminathan ffi_type **ptr = &type->elements[0];
198*1fd5a2e1SPrashanth Swaminathan
199*1fd5a2e1SPrashanth Swaminathan for (ptr = &type->elements[0]; *ptr ; ptr++)
200*1fd5a2e1SPrashanth Swaminathan {
201*1fd5a2e1SPrashanth Swaminathan int sub_element = hfa_element_type (*ptr, 1);
202*1fd5a2e1SPrashanth Swaminathan if (sub_element == FFI_TYPE_VOID)
203*1fd5a2e1SPrashanth Swaminathan return FFI_TYPE_VOID;
204*1fd5a2e1SPrashanth Swaminathan
205*1fd5a2e1SPrashanth Swaminathan if (element == FFI_TYPE_VOID)
206*1fd5a2e1SPrashanth Swaminathan element = sub_element;
207*1fd5a2e1SPrashanth Swaminathan else if (element != sub_element)
208*1fd5a2e1SPrashanth Swaminathan return FFI_TYPE_VOID;
209*1fd5a2e1SPrashanth Swaminathan }
210*1fd5a2e1SPrashanth Swaminathan }
211*1fd5a2e1SPrashanth Swaminathan break;
212*1fd5a2e1SPrashanth Swaminathan
213*1fd5a2e1SPrashanth Swaminathan default:
214*1fd5a2e1SPrashanth Swaminathan return FFI_TYPE_VOID;
215*1fd5a2e1SPrashanth Swaminathan }
216*1fd5a2e1SPrashanth Swaminathan
217*1fd5a2e1SPrashanth Swaminathan return element;
218*1fd5a2e1SPrashanth Swaminathan }
219*1fd5a2e1SPrashanth Swaminathan
220*1fd5a2e1SPrashanth Swaminathan
221*1fd5a2e1SPrashanth Swaminathan /* Perform machine dependent cif processing. */
222*1fd5a2e1SPrashanth Swaminathan
223*1fd5a2e1SPrashanth Swaminathan static ffi_status
ffi_prep_cif_machdep_core(ffi_cif * cif)224*1fd5a2e1SPrashanth Swaminathan ffi_prep_cif_machdep_core(ffi_cif *cif)
225*1fd5a2e1SPrashanth Swaminathan {
226*1fd5a2e1SPrashanth Swaminathan int flags;
227*1fd5a2e1SPrashanth Swaminathan
228*1fd5a2e1SPrashanth Swaminathan /* Adjust cif->bytes to include space for the bits of the ia64_args frame
229*1fd5a2e1SPrashanth Swaminathan that precedes the integer register portion. The estimate that the
230*1fd5a2e1SPrashanth Swaminathan generic bits did for the argument space required is good enough for the
231*1fd5a2e1SPrashanth Swaminathan integer component. */
232*1fd5a2e1SPrashanth Swaminathan cif->bytes += offsetof(struct ia64_args, gp_regs[0]);
233*1fd5a2e1SPrashanth Swaminathan if (cif->bytes < sizeof(struct ia64_args))
234*1fd5a2e1SPrashanth Swaminathan cif->bytes = sizeof(struct ia64_args);
235*1fd5a2e1SPrashanth Swaminathan
236*1fd5a2e1SPrashanth Swaminathan /* Set the return type flag. */
237*1fd5a2e1SPrashanth Swaminathan flags = cif->rtype->type;
238*1fd5a2e1SPrashanth Swaminathan switch (cif->rtype->type)
239*1fd5a2e1SPrashanth Swaminathan {
240*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
241*1fd5a2e1SPrashanth Swaminathan /* Leave FFI_TYPE_LONGDOUBLE as meaning double extended precision,
242*1fd5a2e1SPrashanth Swaminathan and encode quad precision as a two-word integer structure. */
243*1fd5a2e1SPrashanth Swaminathan if (LDBL_MANT_DIG != 64)
244*1fd5a2e1SPrashanth Swaminathan flags = FFI_IA64_TYPE_SMALL_STRUCT | (16 << 8);
245*1fd5a2e1SPrashanth Swaminathan break;
246*1fd5a2e1SPrashanth Swaminathan
247*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
248*1fd5a2e1SPrashanth Swaminathan {
249*1fd5a2e1SPrashanth Swaminathan size_t size = cif->rtype->size;
250*1fd5a2e1SPrashanth Swaminathan int hfa_type = hfa_element_type (cif->rtype, 0);
251*1fd5a2e1SPrashanth Swaminathan
252*1fd5a2e1SPrashanth Swaminathan if (hfa_type != FFI_TYPE_VOID)
253*1fd5a2e1SPrashanth Swaminathan {
254*1fd5a2e1SPrashanth Swaminathan size_t nelts = size / hfa_type_size (hfa_type);
255*1fd5a2e1SPrashanth Swaminathan if (nelts <= 8)
256*1fd5a2e1SPrashanth Swaminathan flags = hfa_type | (size << 8);
257*1fd5a2e1SPrashanth Swaminathan }
258*1fd5a2e1SPrashanth Swaminathan else
259*1fd5a2e1SPrashanth Swaminathan {
260*1fd5a2e1SPrashanth Swaminathan if (size <= 32)
261*1fd5a2e1SPrashanth Swaminathan flags = FFI_IA64_TYPE_SMALL_STRUCT | (size << 8);
262*1fd5a2e1SPrashanth Swaminathan }
263*1fd5a2e1SPrashanth Swaminathan }
264*1fd5a2e1SPrashanth Swaminathan break;
265*1fd5a2e1SPrashanth Swaminathan
266*1fd5a2e1SPrashanth Swaminathan default:
267*1fd5a2e1SPrashanth Swaminathan break;
268*1fd5a2e1SPrashanth Swaminathan }
269*1fd5a2e1SPrashanth Swaminathan cif->flags = flags;
270*1fd5a2e1SPrashanth Swaminathan
271*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
272*1fd5a2e1SPrashanth Swaminathan }
273*1fd5a2e1SPrashanth Swaminathan
274*1fd5a2e1SPrashanth Swaminathan ffi_status
ffi_prep_cif_machdep(ffi_cif * cif)275*1fd5a2e1SPrashanth Swaminathan ffi_prep_cif_machdep(ffi_cif *cif)
276*1fd5a2e1SPrashanth Swaminathan {
277*1fd5a2e1SPrashanth Swaminathan cif->nfixedargs = cif->nargs;
278*1fd5a2e1SPrashanth Swaminathan return ffi_prep_cif_machdep_core(cif);
279*1fd5a2e1SPrashanth Swaminathan }
280*1fd5a2e1SPrashanth Swaminathan
281*1fd5a2e1SPrashanth Swaminathan ffi_status
ffi_prep_cif_machdep_var(ffi_cif * cif,unsigned int nfixedargs,unsigned int ntotalargs MAYBE_UNUSED)282*1fd5a2e1SPrashanth Swaminathan ffi_prep_cif_machdep_var(ffi_cif *cif,
283*1fd5a2e1SPrashanth Swaminathan unsigned int nfixedargs,
284*1fd5a2e1SPrashanth Swaminathan unsigned int ntotalargs MAYBE_UNUSED)
285*1fd5a2e1SPrashanth Swaminathan {
286*1fd5a2e1SPrashanth Swaminathan cif->nfixedargs = nfixedargs;
287*1fd5a2e1SPrashanth Swaminathan return ffi_prep_cif_machdep_core(cif);
288*1fd5a2e1SPrashanth Swaminathan }
289*1fd5a2e1SPrashanth Swaminathan
290*1fd5a2e1SPrashanth Swaminathan extern int ffi_call_unix (struct ia64_args *, PTR64, void (*)(void), UINT64);
291*1fd5a2e1SPrashanth Swaminathan
292*1fd5a2e1SPrashanth Swaminathan void
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)293*1fd5a2e1SPrashanth Swaminathan ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
294*1fd5a2e1SPrashanth Swaminathan {
295*1fd5a2e1SPrashanth Swaminathan struct ia64_args *stack;
296*1fd5a2e1SPrashanth Swaminathan long i, avn, gpcount, fpcount;
297*1fd5a2e1SPrashanth Swaminathan ffi_type **p_arg;
298*1fd5a2e1SPrashanth Swaminathan
299*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (cif->abi == FFI_UNIX);
300*1fd5a2e1SPrashanth Swaminathan
301*1fd5a2e1SPrashanth Swaminathan /* If we have no spot for a return value, make one. */
302*1fd5a2e1SPrashanth Swaminathan if (rvalue == NULL && cif->rtype->type != FFI_TYPE_VOID)
303*1fd5a2e1SPrashanth Swaminathan rvalue = alloca (cif->rtype->size);
304*1fd5a2e1SPrashanth Swaminathan
305*1fd5a2e1SPrashanth Swaminathan /* Allocate the stack frame. */
306*1fd5a2e1SPrashanth Swaminathan stack = alloca (cif->bytes);
307*1fd5a2e1SPrashanth Swaminathan
308*1fd5a2e1SPrashanth Swaminathan gpcount = fpcount = 0;
309*1fd5a2e1SPrashanth Swaminathan avn = cif->nargs;
310*1fd5a2e1SPrashanth Swaminathan for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
311*1fd5a2e1SPrashanth Swaminathan {
312*1fd5a2e1SPrashanth Swaminathan switch ((*p_arg)->type)
313*1fd5a2e1SPrashanth Swaminathan {
314*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
315*1fd5a2e1SPrashanth Swaminathan stack->gp_regs[gpcount++] = *(SINT8 *)avalue[i];
316*1fd5a2e1SPrashanth Swaminathan break;
317*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
318*1fd5a2e1SPrashanth Swaminathan stack->gp_regs[gpcount++] = *(UINT8 *)avalue[i];
319*1fd5a2e1SPrashanth Swaminathan break;
320*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
321*1fd5a2e1SPrashanth Swaminathan stack->gp_regs[gpcount++] = *(SINT16 *)avalue[i];
322*1fd5a2e1SPrashanth Swaminathan break;
323*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
324*1fd5a2e1SPrashanth Swaminathan stack->gp_regs[gpcount++] = *(UINT16 *)avalue[i];
325*1fd5a2e1SPrashanth Swaminathan break;
326*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
327*1fd5a2e1SPrashanth Swaminathan stack->gp_regs[gpcount++] = *(SINT32 *)avalue[i];
328*1fd5a2e1SPrashanth Swaminathan break;
329*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
330*1fd5a2e1SPrashanth Swaminathan stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i];
331*1fd5a2e1SPrashanth Swaminathan break;
332*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
333*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
334*1fd5a2e1SPrashanth Swaminathan stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i];
335*1fd5a2e1SPrashanth Swaminathan break;
336*1fd5a2e1SPrashanth Swaminathan
337*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
338*1fd5a2e1SPrashanth Swaminathan stack->gp_regs[gpcount++] = (UINT64)(PTR64) *(void **)avalue[i];
339*1fd5a2e1SPrashanth Swaminathan break;
340*1fd5a2e1SPrashanth Swaminathan
341*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
342*1fd5a2e1SPrashanth Swaminathan if (gpcount < 8 && fpcount < 8)
343*1fd5a2e1SPrashanth Swaminathan stf_spill (&stack->fp_regs[fpcount++], *(float *)avalue[i]);
344*1fd5a2e1SPrashanth Swaminathan {
345*1fd5a2e1SPrashanth Swaminathan UINT32 tmp;
346*1fd5a2e1SPrashanth Swaminathan memcpy (&tmp, avalue[i], sizeof (UINT32));
347*1fd5a2e1SPrashanth Swaminathan stack->gp_regs[gpcount++] = tmp;
348*1fd5a2e1SPrashanth Swaminathan }
349*1fd5a2e1SPrashanth Swaminathan break;
350*1fd5a2e1SPrashanth Swaminathan
351*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
352*1fd5a2e1SPrashanth Swaminathan if (gpcount < 8 && fpcount < 8)
353*1fd5a2e1SPrashanth Swaminathan stf_spill (&stack->fp_regs[fpcount++], *(double *)avalue[i]);
354*1fd5a2e1SPrashanth Swaminathan memcpy (&stack->gp_regs[gpcount++], avalue[i], sizeof (UINT64));
355*1fd5a2e1SPrashanth Swaminathan break;
356*1fd5a2e1SPrashanth Swaminathan
357*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
358*1fd5a2e1SPrashanth Swaminathan if (gpcount & 1)
359*1fd5a2e1SPrashanth Swaminathan gpcount++;
360*1fd5a2e1SPrashanth Swaminathan if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
361*1fd5a2e1SPrashanth Swaminathan stf_spill (&stack->fp_regs[fpcount++], *(__float80 *)avalue[i]);
362*1fd5a2e1SPrashanth Swaminathan memcpy (&stack->gp_regs[gpcount], avalue[i], 16);
363*1fd5a2e1SPrashanth Swaminathan gpcount += 2;
364*1fd5a2e1SPrashanth Swaminathan break;
365*1fd5a2e1SPrashanth Swaminathan
366*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
367*1fd5a2e1SPrashanth Swaminathan {
368*1fd5a2e1SPrashanth Swaminathan size_t size = (*p_arg)->size;
369*1fd5a2e1SPrashanth Swaminathan size_t align = (*p_arg)->alignment;
370*1fd5a2e1SPrashanth Swaminathan int hfa_type = hfa_element_type (*p_arg, 0);
371*1fd5a2e1SPrashanth Swaminathan
372*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (align <= 16);
373*1fd5a2e1SPrashanth Swaminathan if (align == 16 && (gpcount & 1))
374*1fd5a2e1SPrashanth Swaminathan gpcount++;
375*1fd5a2e1SPrashanth Swaminathan
376*1fd5a2e1SPrashanth Swaminathan if (hfa_type != FFI_TYPE_VOID)
377*1fd5a2e1SPrashanth Swaminathan {
378*1fd5a2e1SPrashanth Swaminathan size_t hfa_size = hfa_type_size (hfa_type);
379*1fd5a2e1SPrashanth Swaminathan size_t offset = 0;
380*1fd5a2e1SPrashanth Swaminathan size_t gp_offset = gpcount * 8;
381*1fd5a2e1SPrashanth Swaminathan
382*1fd5a2e1SPrashanth Swaminathan while (fpcount < 8
383*1fd5a2e1SPrashanth Swaminathan && offset < size
384*1fd5a2e1SPrashanth Swaminathan && gp_offset < 8 * 8)
385*1fd5a2e1SPrashanth Swaminathan {
386*1fd5a2e1SPrashanth Swaminathan hfa_type_load (&stack->fp_regs[fpcount], hfa_type,
387*1fd5a2e1SPrashanth Swaminathan avalue[i] + offset);
388*1fd5a2e1SPrashanth Swaminathan offset += hfa_size;
389*1fd5a2e1SPrashanth Swaminathan gp_offset += hfa_size;
390*1fd5a2e1SPrashanth Swaminathan fpcount += 1;
391*1fd5a2e1SPrashanth Swaminathan }
392*1fd5a2e1SPrashanth Swaminathan }
393*1fd5a2e1SPrashanth Swaminathan
394*1fd5a2e1SPrashanth Swaminathan memcpy (&stack->gp_regs[gpcount], avalue[i], size);
395*1fd5a2e1SPrashanth Swaminathan gpcount += (size + 7) / 8;
396*1fd5a2e1SPrashanth Swaminathan }
397*1fd5a2e1SPrashanth Swaminathan break;
398*1fd5a2e1SPrashanth Swaminathan
399*1fd5a2e1SPrashanth Swaminathan default:
400*1fd5a2e1SPrashanth Swaminathan abort ();
401*1fd5a2e1SPrashanth Swaminathan }
402*1fd5a2e1SPrashanth Swaminathan }
403*1fd5a2e1SPrashanth Swaminathan
404*1fd5a2e1SPrashanth Swaminathan ffi_call_unix (stack, rvalue, fn, cif->flags);
405*1fd5a2e1SPrashanth Swaminathan }
406*1fd5a2e1SPrashanth Swaminathan
407*1fd5a2e1SPrashanth Swaminathan /* Closures represent a pair consisting of a function pointer, and
408*1fd5a2e1SPrashanth Swaminathan some user data. A closure is invoked by reinterpreting the closure
409*1fd5a2e1SPrashanth Swaminathan as a function pointer, and branching to it. Thus we can make an
410*1fd5a2e1SPrashanth Swaminathan interpreted function callable as a C function: We turn the
411*1fd5a2e1SPrashanth Swaminathan interpreter itself, together with a pointer specifying the
412*1fd5a2e1SPrashanth Swaminathan interpreted procedure, into a closure.
413*1fd5a2e1SPrashanth Swaminathan
414*1fd5a2e1SPrashanth Swaminathan For IA64, function pointer are already pairs consisting of a code
415*1fd5a2e1SPrashanth Swaminathan pointer, and a gp pointer. The latter is needed to access global
416*1fd5a2e1SPrashanth Swaminathan variables. Here we set up such a pair as the first two words of
417*1fd5a2e1SPrashanth Swaminathan the closure (in the "trampoline" area), but we replace the gp
418*1fd5a2e1SPrashanth Swaminathan pointer with a pointer to the closure itself. We also add the real
419*1fd5a2e1SPrashanth Swaminathan gp pointer to the closure. This allows the function entry code to
420*1fd5a2e1SPrashanth Swaminathan both retrieve the user data, and to restore the correct gp pointer. */
421*1fd5a2e1SPrashanth Swaminathan
422*1fd5a2e1SPrashanth Swaminathan extern void ffi_closure_unix ();
423*1fd5a2e1SPrashanth Swaminathan
424*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)425*1fd5a2e1SPrashanth Swaminathan ffi_prep_closure_loc (ffi_closure* closure,
426*1fd5a2e1SPrashanth Swaminathan ffi_cif* cif,
427*1fd5a2e1SPrashanth Swaminathan void (*fun)(ffi_cif*,void*,void**,void*),
428*1fd5a2e1SPrashanth Swaminathan void *user_data,
429*1fd5a2e1SPrashanth Swaminathan void *codeloc)
430*1fd5a2e1SPrashanth Swaminathan {
431*1fd5a2e1SPrashanth Swaminathan /* The layout of a function descriptor. A C function pointer really
432*1fd5a2e1SPrashanth Swaminathan points to one of these. */
433*1fd5a2e1SPrashanth Swaminathan struct ia64_fd
434*1fd5a2e1SPrashanth Swaminathan {
435*1fd5a2e1SPrashanth Swaminathan UINT64 code_pointer;
436*1fd5a2e1SPrashanth Swaminathan UINT64 gp;
437*1fd5a2e1SPrashanth Swaminathan };
438*1fd5a2e1SPrashanth Swaminathan
439*1fd5a2e1SPrashanth Swaminathan struct ffi_ia64_trampoline_struct
440*1fd5a2e1SPrashanth Swaminathan {
441*1fd5a2e1SPrashanth Swaminathan UINT64 code_pointer; /* Pointer to ffi_closure_unix. */
442*1fd5a2e1SPrashanth Swaminathan UINT64 fake_gp; /* Pointer to closure, installed as gp. */
443*1fd5a2e1SPrashanth Swaminathan UINT64 real_gp; /* Real gp value. */
444*1fd5a2e1SPrashanth Swaminathan };
445*1fd5a2e1SPrashanth Swaminathan
446*1fd5a2e1SPrashanth Swaminathan struct ffi_ia64_trampoline_struct *tramp;
447*1fd5a2e1SPrashanth Swaminathan struct ia64_fd *fd;
448*1fd5a2e1SPrashanth Swaminathan
449*1fd5a2e1SPrashanth Swaminathan if (cif->abi != FFI_UNIX)
450*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
451*1fd5a2e1SPrashanth Swaminathan
452*1fd5a2e1SPrashanth Swaminathan tramp = (struct ffi_ia64_trampoline_struct *)closure->tramp;
453*1fd5a2e1SPrashanth Swaminathan fd = (struct ia64_fd *)(void *)ffi_closure_unix;
454*1fd5a2e1SPrashanth Swaminathan
455*1fd5a2e1SPrashanth Swaminathan tramp->code_pointer = fd->code_pointer;
456*1fd5a2e1SPrashanth Swaminathan tramp->real_gp = fd->gp;
457*1fd5a2e1SPrashanth Swaminathan tramp->fake_gp = (UINT64)(PTR64)codeloc;
458*1fd5a2e1SPrashanth Swaminathan closure->cif = cif;
459*1fd5a2e1SPrashanth Swaminathan closure->user_data = user_data;
460*1fd5a2e1SPrashanth Swaminathan closure->fun = fun;
461*1fd5a2e1SPrashanth Swaminathan
462*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
463*1fd5a2e1SPrashanth Swaminathan }
464*1fd5a2e1SPrashanth Swaminathan
465*1fd5a2e1SPrashanth Swaminathan
466*1fd5a2e1SPrashanth Swaminathan UINT64
ffi_closure_unix_inner(ffi_closure * closure,struct ia64_args * stack,void * rvalue,void * r8)467*1fd5a2e1SPrashanth Swaminathan ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack,
468*1fd5a2e1SPrashanth Swaminathan void *rvalue, void *r8)
469*1fd5a2e1SPrashanth Swaminathan {
470*1fd5a2e1SPrashanth Swaminathan ffi_cif *cif;
471*1fd5a2e1SPrashanth Swaminathan void **avalue;
472*1fd5a2e1SPrashanth Swaminathan ffi_type **p_arg;
473*1fd5a2e1SPrashanth Swaminathan long i, avn, gpcount, fpcount, nfixedargs;
474*1fd5a2e1SPrashanth Swaminathan
475*1fd5a2e1SPrashanth Swaminathan cif = closure->cif;
476*1fd5a2e1SPrashanth Swaminathan avn = cif->nargs;
477*1fd5a2e1SPrashanth Swaminathan nfixedargs = cif->nfixedargs;
478*1fd5a2e1SPrashanth Swaminathan avalue = alloca (avn * sizeof (void *));
479*1fd5a2e1SPrashanth Swaminathan
480*1fd5a2e1SPrashanth Swaminathan /* If the structure return value is passed in memory get that location
481*1fd5a2e1SPrashanth Swaminathan from r8 so as to pass the value directly back to the caller. */
482*1fd5a2e1SPrashanth Swaminathan if (cif->flags == FFI_TYPE_STRUCT)
483*1fd5a2e1SPrashanth Swaminathan rvalue = r8;
484*1fd5a2e1SPrashanth Swaminathan
485*1fd5a2e1SPrashanth Swaminathan gpcount = fpcount = 0;
486*1fd5a2e1SPrashanth Swaminathan for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
487*1fd5a2e1SPrashanth Swaminathan {
488*1fd5a2e1SPrashanth Swaminathan int named = i < nfixedargs;
489*1fd5a2e1SPrashanth Swaminathan switch ((*p_arg)->type)
490*1fd5a2e1SPrashanth Swaminathan {
491*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
492*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
493*1fd5a2e1SPrashanth Swaminathan avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 1);
494*1fd5a2e1SPrashanth Swaminathan break;
495*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
496*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
497*1fd5a2e1SPrashanth Swaminathan avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 2);
498*1fd5a2e1SPrashanth Swaminathan break;
499*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
500*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
501*1fd5a2e1SPrashanth Swaminathan avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 4);
502*1fd5a2e1SPrashanth Swaminathan break;
503*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
504*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
505*1fd5a2e1SPrashanth Swaminathan avalue[i] = &stack->gp_regs[gpcount++];
506*1fd5a2e1SPrashanth Swaminathan break;
507*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
508*1fd5a2e1SPrashanth Swaminathan avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], sizeof(void*));
509*1fd5a2e1SPrashanth Swaminathan break;
510*1fd5a2e1SPrashanth Swaminathan
511*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
512*1fd5a2e1SPrashanth Swaminathan if (named && gpcount < 8 && fpcount < 8)
513*1fd5a2e1SPrashanth Swaminathan {
514*1fd5a2e1SPrashanth Swaminathan fpreg *addr = &stack->fp_regs[fpcount++];
515*1fd5a2e1SPrashanth Swaminathan float result;
516*1fd5a2e1SPrashanth Swaminathan avalue[i] = addr;
517*1fd5a2e1SPrashanth Swaminathan ldf_fill (result, addr);
518*1fd5a2e1SPrashanth Swaminathan *(float *)addr = result;
519*1fd5a2e1SPrashanth Swaminathan }
520*1fd5a2e1SPrashanth Swaminathan else
521*1fd5a2e1SPrashanth Swaminathan avalue[i] = endian_adjust(&stack->gp_regs[gpcount], 4);
522*1fd5a2e1SPrashanth Swaminathan gpcount++;
523*1fd5a2e1SPrashanth Swaminathan break;
524*1fd5a2e1SPrashanth Swaminathan
525*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
526*1fd5a2e1SPrashanth Swaminathan if (named && gpcount < 8 && fpcount < 8)
527*1fd5a2e1SPrashanth Swaminathan {
528*1fd5a2e1SPrashanth Swaminathan fpreg *addr = &stack->fp_regs[fpcount++];
529*1fd5a2e1SPrashanth Swaminathan double result;
530*1fd5a2e1SPrashanth Swaminathan avalue[i] = addr;
531*1fd5a2e1SPrashanth Swaminathan ldf_fill (result, addr);
532*1fd5a2e1SPrashanth Swaminathan *(double *)addr = result;
533*1fd5a2e1SPrashanth Swaminathan }
534*1fd5a2e1SPrashanth Swaminathan else
535*1fd5a2e1SPrashanth Swaminathan avalue[i] = &stack->gp_regs[gpcount];
536*1fd5a2e1SPrashanth Swaminathan gpcount++;
537*1fd5a2e1SPrashanth Swaminathan break;
538*1fd5a2e1SPrashanth Swaminathan
539*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
540*1fd5a2e1SPrashanth Swaminathan if (gpcount & 1)
541*1fd5a2e1SPrashanth Swaminathan gpcount++;
542*1fd5a2e1SPrashanth Swaminathan if (LDBL_MANT_DIG == 64 && named && gpcount < 8 && fpcount < 8)
543*1fd5a2e1SPrashanth Swaminathan {
544*1fd5a2e1SPrashanth Swaminathan fpreg *addr = &stack->fp_regs[fpcount++];
545*1fd5a2e1SPrashanth Swaminathan __float80 result;
546*1fd5a2e1SPrashanth Swaminathan avalue[i] = addr;
547*1fd5a2e1SPrashanth Swaminathan ldf_fill (result, addr);
548*1fd5a2e1SPrashanth Swaminathan *(__float80 *)addr = result;
549*1fd5a2e1SPrashanth Swaminathan }
550*1fd5a2e1SPrashanth Swaminathan else
551*1fd5a2e1SPrashanth Swaminathan avalue[i] = &stack->gp_regs[gpcount];
552*1fd5a2e1SPrashanth Swaminathan gpcount += 2;
553*1fd5a2e1SPrashanth Swaminathan break;
554*1fd5a2e1SPrashanth Swaminathan
555*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
556*1fd5a2e1SPrashanth Swaminathan {
557*1fd5a2e1SPrashanth Swaminathan size_t size = (*p_arg)->size;
558*1fd5a2e1SPrashanth Swaminathan size_t align = (*p_arg)->alignment;
559*1fd5a2e1SPrashanth Swaminathan int hfa_type = hfa_element_type (*p_arg, 0);
560*1fd5a2e1SPrashanth Swaminathan
561*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (align <= 16);
562*1fd5a2e1SPrashanth Swaminathan if (align == 16 && (gpcount & 1))
563*1fd5a2e1SPrashanth Swaminathan gpcount++;
564*1fd5a2e1SPrashanth Swaminathan
565*1fd5a2e1SPrashanth Swaminathan if (hfa_type != FFI_TYPE_VOID)
566*1fd5a2e1SPrashanth Swaminathan {
567*1fd5a2e1SPrashanth Swaminathan size_t hfa_size = hfa_type_size (hfa_type);
568*1fd5a2e1SPrashanth Swaminathan size_t offset = 0;
569*1fd5a2e1SPrashanth Swaminathan size_t gp_offset = gpcount * 8;
570*1fd5a2e1SPrashanth Swaminathan void *addr = alloca (size);
571*1fd5a2e1SPrashanth Swaminathan
572*1fd5a2e1SPrashanth Swaminathan avalue[i] = addr;
573*1fd5a2e1SPrashanth Swaminathan
574*1fd5a2e1SPrashanth Swaminathan while (fpcount < 8
575*1fd5a2e1SPrashanth Swaminathan && offset < size
576*1fd5a2e1SPrashanth Swaminathan && gp_offset < 8 * 8)
577*1fd5a2e1SPrashanth Swaminathan {
578*1fd5a2e1SPrashanth Swaminathan hfa_type_store (hfa_type, addr + offset,
579*1fd5a2e1SPrashanth Swaminathan &stack->fp_regs[fpcount]);
580*1fd5a2e1SPrashanth Swaminathan offset += hfa_size;
581*1fd5a2e1SPrashanth Swaminathan gp_offset += hfa_size;
582*1fd5a2e1SPrashanth Swaminathan fpcount += 1;
583*1fd5a2e1SPrashanth Swaminathan }
584*1fd5a2e1SPrashanth Swaminathan
585*1fd5a2e1SPrashanth Swaminathan if (offset < size)
586*1fd5a2e1SPrashanth Swaminathan memcpy (addr + offset, (char *)stack->gp_regs + gp_offset,
587*1fd5a2e1SPrashanth Swaminathan size - offset);
588*1fd5a2e1SPrashanth Swaminathan }
589*1fd5a2e1SPrashanth Swaminathan else
590*1fd5a2e1SPrashanth Swaminathan avalue[i] = &stack->gp_regs[gpcount];
591*1fd5a2e1SPrashanth Swaminathan
592*1fd5a2e1SPrashanth Swaminathan gpcount += (size + 7) / 8;
593*1fd5a2e1SPrashanth Swaminathan }
594*1fd5a2e1SPrashanth Swaminathan break;
595*1fd5a2e1SPrashanth Swaminathan
596*1fd5a2e1SPrashanth Swaminathan default:
597*1fd5a2e1SPrashanth Swaminathan abort ();
598*1fd5a2e1SPrashanth Swaminathan }
599*1fd5a2e1SPrashanth Swaminathan }
600*1fd5a2e1SPrashanth Swaminathan
601*1fd5a2e1SPrashanth Swaminathan closure->fun (cif, rvalue, avalue, closure->user_data);
602*1fd5a2e1SPrashanth Swaminathan
603*1fd5a2e1SPrashanth Swaminathan return cif->flags;
604*1fd5a2e1SPrashanth Swaminathan }
605