1*1fd5a2e1SPrashanth Swaminathan /* -----------------------------------------------------------------------
2*1fd5a2e1SPrashanth Swaminathan ffi.c - Copyright (c) 2013 Tensilica, Inc.
3*1fd5a2e1SPrashanth Swaminathan
4*1fd5a2e1SPrashanth Swaminathan XTENSA Foreign Function Interface
5*1fd5a2e1SPrashanth Swaminathan
6*1fd5a2e1SPrashanth Swaminathan Permission is hereby granted, free of charge, to any person obtaining
7*1fd5a2e1SPrashanth Swaminathan a copy of this software and associated documentation files (the
8*1fd5a2e1SPrashanth Swaminathan ``Software''), to deal in the Software without restriction, including
9*1fd5a2e1SPrashanth Swaminathan without limitation the rights to use, copy, modify, merge, publish,
10*1fd5a2e1SPrashanth Swaminathan distribute, sublicense, and/or sell copies of the Software, and to
11*1fd5a2e1SPrashanth Swaminathan permit persons to whom the Software is furnished to do so, subject to
12*1fd5a2e1SPrashanth Swaminathan the following conditions:
13*1fd5a2e1SPrashanth Swaminathan
14*1fd5a2e1SPrashanth Swaminathan The above copyright notice and this permission notice shall be included
15*1fd5a2e1SPrashanth Swaminathan in all copies or substantial portions of the Software.
16*1fd5a2e1SPrashanth Swaminathan
17*1fd5a2e1SPrashanth Swaminathan THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
18*1fd5a2e1SPrashanth Swaminathan EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19*1fd5a2e1SPrashanth Swaminathan MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20*1fd5a2e1SPrashanth Swaminathan NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21*1fd5a2e1SPrashanth Swaminathan HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22*1fd5a2e1SPrashanth Swaminathan WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23*1fd5a2e1SPrashanth Swaminathan OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24*1fd5a2e1SPrashanth Swaminathan DEALINGS IN THE SOFTWARE.
25*1fd5a2e1SPrashanth Swaminathan ----------------------------------------------------------------------- */
26*1fd5a2e1SPrashanth Swaminathan
27*1fd5a2e1SPrashanth Swaminathan #include <ffi.h>
28*1fd5a2e1SPrashanth Swaminathan #include <ffi_common.h>
29*1fd5a2e1SPrashanth Swaminathan
30*1fd5a2e1SPrashanth Swaminathan /*
31*1fd5a2e1SPrashanth Swaminathan |----------------------------------------|
32*1fd5a2e1SPrashanth Swaminathan | |
33*1fd5a2e1SPrashanth Swaminathan on entry to ffi_call ----> |----------------------------------------|
34*1fd5a2e1SPrashanth Swaminathan | caller stack frame for registers a0-a3 |
35*1fd5a2e1SPrashanth Swaminathan |----------------------------------------|
36*1fd5a2e1SPrashanth Swaminathan | |
37*1fd5a2e1SPrashanth Swaminathan | additional arguments |
38*1fd5a2e1SPrashanth Swaminathan entry of the function ---> |----------------------------------------|
39*1fd5a2e1SPrashanth Swaminathan | copy of function arguments a2-a7 |
40*1fd5a2e1SPrashanth Swaminathan | - - - - - - - - - - - - - |
41*1fd5a2e1SPrashanth Swaminathan | |
42*1fd5a2e1SPrashanth Swaminathan
43*1fd5a2e1SPrashanth Swaminathan The area below the entry line becomes the new stack frame for the function.
44*1fd5a2e1SPrashanth Swaminathan
45*1fd5a2e1SPrashanth Swaminathan */
46*1fd5a2e1SPrashanth Swaminathan
47*1fd5a2e1SPrashanth Swaminathan
48*1fd5a2e1SPrashanth Swaminathan #define FFI_TYPE_STRUCT_REGS FFI_TYPE_LAST
49*1fd5a2e1SPrashanth Swaminathan
50*1fd5a2e1SPrashanth Swaminathan
51*1fd5a2e1SPrashanth Swaminathan extern void ffi_call_SYSV(void *rvalue, unsigned rsize, unsigned flags,
52*1fd5a2e1SPrashanth Swaminathan void(*fn)(void), unsigned nbytes, extended_cif*);
53*1fd5a2e1SPrashanth Swaminathan extern void ffi_closure_SYSV(void) FFI_HIDDEN;
54*1fd5a2e1SPrashanth Swaminathan
ffi_prep_cif_machdep(ffi_cif * cif)55*1fd5a2e1SPrashanth Swaminathan ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
56*1fd5a2e1SPrashanth Swaminathan {
57*1fd5a2e1SPrashanth Swaminathan switch(cif->rtype->type) {
58*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
59*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
60*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
61*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
62*1fd5a2e1SPrashanth Swaminathan cif->flags = cif->rtype->type;
63*1fd5a2e1SPrashanth Swaminathan break;
64*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_VOID:
65*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
66*1fd5a2e1SPrashanth Swaminathan cif->flags = FFI_TYPE_UINT32;
67*1fd5a2e1SPrashanth Swaminathan break;
68*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
69*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
70*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
71*1fd5a2e1SPrashanth Swaminathan cif->flags = FFI_TYPE_UINT64; // cif->rtype->type;
72*1fd5a2e1SPrashanth Swaminathan break;
73*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
74*1fd5a2e1SPrashanth Swaminathan cif->flags = FFI_TYPE_STRUCT; //_REGS;
75*1fd5a2e1SPrashanth Swaminathan /* Up to 16 bytes are returned in registers */
76*1fd5a2e1SPrashanth Swaminathan if (cif->rtype->size > 4 * 4) {
77*1fd5a2e1SPrashanth Swaminathan /* returned structure is referenced by a register; use 8 bytes
78*1fd5a2e1SPrashanth Swaminathan (including 4 bytes for potential additional alignment) */
79*1fd5a2e1SPrashanth Swaminathan cif->flags = FFI_TYPE_STRUCT;
80*1fd5a2e1SPrashanth Swaminathan cif->bytes += 8;
81*1fd5a2e1SPrashanth Swaminathan }
82*1fd5a2e1SPrashanth Swaminathan break;
83*1fd5a2e1SPrashanth Swaminathan
84*1fd5a2e1SPrashanth Swaminathan default:
85*1fd5a2e1SPrashanth Swaminathan cif->flags = FFI_TYPE_UINT32;
86*1fd5a2e1SPrashanth Swaminathan break;
87*1fd5a2e1SPrashanth Swaminathan }
88*1fd5a2e1SPrashanth Swaminathan
89*1fd5a2e1SPrashanth Swaminathan /* Round the stack up to a full 4 register frame, just in case
90*1fd5a2e1SPrashanth Swaminathan (we use this size in movsp). This way, it's also a multiple of
91*1fd5a2e1SPrashanth Swaminathan 8 bytes for 64-bit arguments. */
92*1fd5a2e1SPrashanth Swaminathan cif->bytes = FFI_ALIGN(cif->bytes, 16);
93*1fd5a2e1SPrashanth Swaminathan
94*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
95*1fd5a2e1SPrashanth Swaminathan }
96*1fd5a2e1SPrashanth Swaminathan
ffi_prep_args(extended_cif * ecif,unsigned char * stack)97*1fd5a2e1SPrashanth Swaminathan void ffi_prep_args(extended_cif *ecif, unsigned char* stack)
98*1fd5a2e1SPrashanth Swaminathan {
99*1fd5a2e1SPrashanth Swaminathan unsigned int i;
100*1fd5a2e1SPrashanth Swaminathan unsigned long *addr;
101*1fd5a2e1SPrashanth Swaminathan ffi_type **ptr;
102*1fd5a2e1SPrashanth Swaminathan
103*1fd5a2e1SPrashanth Swaminathan union {
104*1fd5a2e1SPrashanth Swaminathan void **v;
105*1fd5a2e1SPrashanth Swaminathan char **c;
106*1fd5a2e1SPrashanth Swaminathan signed char **sc;
107*1fd5a2e1SPrashanth Swaminathan unsigned char **uc;
108*1fd5a2e1SPrashanth Swaminathan signed short **ss;
109*1fd5a2e1SPrashanth Swaminathan unsigned short **us;
110*1fd5a2e1SPrashanth Swaminathan unsigned int **i;
111*1fd5a2e1SPrashanth Swaminathan long long **ll;
112*1fd5a2e1SPrashanth Swaminathan float **f;
113*1fd5a2e1SPrashanth Swaminathan double **d;
114*1fd5a2e1SPrashanth Swaminathan } p_argv;
115*1fd5a2e1SPrashanth Swaminathan
116*1fd5a2e1SPrashanth Swaminathan /* Verify that everything is aligned up properly */
117*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (((unsigned long) stack & 0x7) == 0);
118*1fd5a2e1SPrashanth Swaminathan
119*1fd5a2e1SPrashanth Swaminathan p_argv.v = ecif->avalue;
120*1fd5a2e1SPrashanth Swaminathan addr = (unsigned long*)stack;
121*1fd5a2e1SPrashanth Swaminathan
122*1fd5a2e1SPrashanth Swaminathan /* structures with a size greater than 16 bytes are passed in memory */
123*1fd5a2e1SPrashanth Swaminathan if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 16)
124*1fd5a2e1SPrashanth Swaminathan {
125*1fd5a2e1SPrashanth Swaminathan *addr++ = (unsigned long)ecif->rvalue;
126*1fd5a2e1SPrashanth Swaminathan }
127*1fd5a2e1SPrashanth Swaminathan
128*1fd5a2e1SPrashanth Swaminathan for (i = ecif->cif->nargs, ptr = ecif->cif->arg_types;
129*1fd5a2e1SPrashanth Swaminathan i > 0;
130*1fd5a2e1SPrashanth Swaminathan i--, ptr++, p_argv.v++)
131*1fd5a2e1SPrashanth Swaminathan {
132*1fd5a2e1SPrashanth Swaminathan switch ((*ptr)->type)
133*1fd5a2e1SPrashanth Swaminathan {
134*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
135*1fd5a2e1SPrashanth Swaminathan *addr++ = **p_argv.sc;
136*1fd5a2e1SPrashanth Swaminathan break;
137*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
138*1fd5a2e1SPrashanth Swaminathan *addr++ = **p_argv.uc;
139*1fd5a2e1SPrashanth Swaminathan break;
140*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
141*1fd5a2e1SPrashanth Swaminathan *addr++ = **p_argv.ss;
142*1fd5a2e1SPrashanth Swaminathan break;
143*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
144*1fd5a2e1SPrashanth Swaminathan *addr++ = **p_argv.us;
145*1fd5a2e1SPrashanth Swaminathan break;
146*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
147*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_INT:
148*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
149*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
150*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
151*1fd5a2e1SPrashanth Swaminathan *addr++ = **p_argv.i;
152*1fd5a2e1SPrashanth Swaminathan break;
153*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
154*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
155*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
156*1fd5a2e1SPrashanth Swaminathan if (((unsigned long)addr & 4) != 0)
157*1fd5a2e1SPrashanth Swaminathan addr++;
158*1fd5a2e1SPrashanth Swaminathan *(unsigned long long*)addr = **p_argv.ll;
159*1fd5a2e1SPrashanth Swaminathan addr += sizeof(unsigned long long) / sizeof (addr);
160*1fd5a2e1SPrashanth Swaminathan break;
161*1fd5a2e1SPrashanth Swaminathan
162*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
163*1fd5a2e1SPrashanth Swaminathan {
164*1fd5a2e1SPrashanth Swaminathan unsigned long offs;
165*1fd5a2e1SPrashanth Swaminathan unsigned long size;
166*1fd5a2e1SPrashanth Swaminathan
167*1fd5a2e1SPrashanth Swaminathan if (((unsigned long)addr & 4) != 0 && (*ptr)->alignment > 4)
168*1fd5a2e1SPrashanth Swaminathan addr++;
169*1fd5a2e1SPrashanth Swaminathan
170*1fd5a2e1SPrashanth Swaminathan offs = (unsigned long) addr - (unsigned long) stack;
171*1fd5a2e1SPrashanth Swaminathan size = (*ptr)->size;
172*1fd5a2e1SPrashanth Swaminathan
173*1fd5a2e1SPrashanth Swaminathan /* Entire structure must fit the argument registers or referenced */
174*1fd5a2e1SPrashanth Swaminathan if (offs < FFI_REGISTER_NARGS * 4
175*1fd5a2e1SPrashanth Swaminathan && offs + size > FFI_REGISTER_NARGS * 4)
176*1fd5a2e1SPrashanth Swaminathan addr = (unsigned long*) (stack + FFI_REGISTER_NARGS * 4);
177*1fd5a2e1SPrashanth Swaminathan
178*1fd5a2e1SPrashanth Swaminathan memcpy((char*) addr, *p_argv.c, size);
179*1fd5a2e1SPrashanth Swaminathan addr += (size + 3) / 4;
180*1fd5a2e1SPrashanth Swaminathan break;
181*1fd5a2e1SPrashanth Swaminathan }
182*1fd5a2e1SPrashanth Swaminathan
183*1fd5a2e1SPrashanth Swaminathan default:
184*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(0);
185*1fd5a2e1SPrashanth Swaminathan }
186*1fd5a2e1SPrashanth Swaminathan }
187*1fd5a2e1SPrashanth Swaminathan }
188*1fd5a2e1SPrashanth Swaminathan
189*1fd5a2e1SPrashanth Swaminathan
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)190*1fd5a2e1SPrashanth Swaminathan void ffi_call(ffi_cif* cif, void(*fn)(void), void *rvalue, void **avalue)
191*1fd5a2e1SPrashanth Swaminathan {
192*1fd5a2e1SPrashanth Swaminathan extended_cif ecif;
193*1fd5a2e1SPrashanth Swaminathan unsigned long rsize = cif->rtype->size;
194*1fd5a2e1SPrashanth Swaminathan int flags = cif->flags;
195*1fd5a2e1SPrashanth Swaminathan void *alloc = NULL;
196*1fd5a2e1SPrashanth Swaminathan
197*1fd5a2e1SPrashanth Swaminathan ecif.cif = cif;
198*1fd5a2e1SPrashanth Swaminathan ecif.avalue = avalue;
199*1fd5a2e1SPrashanth Swaminathan
200*1fd5a2e1SPrashanth Swaminathan /* Note that for structures that are returned in registers (size <= 16 bytes)
201*1fd5a2e1SPrashanth Swaminathan we allocate a temporary buffer and use memcpy to copy it to the final
202*1fd5a2e1SPrashanth Swaminathan destination. The reason is that the target address might be misaligned or
203*1fd5a2e1SPrashanth Swaminathan the length not a multiple of 4 bytes. Handling all those cases would be
204*1fd5a2e1SPrashanth Swaminathan very complex. */
205*1fd5a2e1SPrashanth Swaminathan
206*1fd5a2e1SPrashanth Swaminathan if (flags == FFI_TYPE_STRUCT && (rsize <= 16 || rvalue == NULL))
207*1fd5a2e1SPrashanth Swaminathan {
208*1fd5a2e1SPrashanth Swaminathan alloc = alloca(FFI_ALIGN(rsize, 4));
209*1fd5a2e1SPrashanth Swaminathan ecif.rvalue = alloc;
210*1fd5a2e1SPrashanth Swaminathan }
211*1fd5a2e1SPrashanth Swaminathan else
212*1fd5a2e1SPrashanth Swaminathan {
213*1fd5a2e1SPrashanth Swaminathan ecif.rvalue = rvalue;
214*1fd5a2e1SPrashanth Swaminathan }
215*1fd5a2e1SPrashanth Swaminathan
216*1fd5a2e1SPrashanth Swaminathan if (cif->abi != FFI_SYSV)
217*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(0);
218*1fd5a2e1SPrashanth Swaminathan
219*1fd5a2e1SPrashanth Swaminathan ffi_call_SYSV (ecif.rvalue, rsize, cif->flags, fn, cif->bytes, &ecif);
220*1fd5a2e1SPrashanth Swaminathan
221*1fd5a2e1SPrashanth Swaminathan if (alloc != NULL && rvalue != NULL)
222*1fd5a2e1SPrashanth Swaminathan memcpy(rvalue, alloc, rsize);
223*1fd5a2e1SPrashanth Swaminathan }
224*1fd5a2e1SPrashanth Swaminathan
225*1fd5a2e1SPrashanth Swaminathan extern void ffi_trampoline();
226*1fd5a2e1SPrashanth Swaminathan extern void ffi_cacheflush(void* start, void* end);
227*1fd5a2e1SPrashanth Swaminathan
228*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)229*1fd5a2e1SPrashanth Swaminathan ffi_prep_closure_loc (ffi_closure* closure,
230*1fd5a2e1SPrashanth Swaminathan ffi_cif* cif,
231*1fd5a2e1SPrashanth Swaminathan void (*fun)(ffi_cif*, void*, void**, void*),
232*1fd5a2e1SPrashanth Swaminathan void *user_data,
233*1fd5a2e1SPrashanth Swaminathan void *codeloc)
234*1fd5a2e1SPrashanth Swaminathan {
235*1fd5a2e1SPrashanth Swaminathan /* copye trampoline to stack and patch 'ffi_closure_SYSV' pointer */
236*1fd5a2e1SPrashanth Swaminathan memcpy(closure->tramp, ffi_trampoline, FFI_TRAMPOLINE_SIZE);
237*1fd5a2e1SPrashanth Swaminathan *(unsigned int*)(&closure->tramp[8]) = (unsigned int)ffi_closure_SYSV;
238*1fd5a2e1SPrashanth Swaminathan
239*1fd5a2e1SPrashanth Swaminathan // Do we have this function?
240*1fd5a2e1SPrashanth Swaminathan // __builtin___clear_cache(closer->tramp, closer->tramp + FFI_TRAMPOLINE_SIZE)
241*1fd5a2e1SPrashanth Swaminathan ffi_cacheflush(closure->tramp, closure->tramp + FFI_TRAMPOLINE_SIZE);
242*1fd5a2e1SPrashanth Swaminathan
243*1fd5a2e1SPrashanth Swaminathan closure->cif = cif;
244*1fd5a2e1SPrashanth Swaminathan closure->fun = fun;
245*1fd5a2e1SPrashanth Swaminathan closure->user_data = user_data;
246*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
247*1fd5a2e1SPrashanth Swaminathan }
248*1fd5a2e1SPrashanth Swaminathan
249*1fd5a2e1SPrashanth Swaminathan
250*1fd5a2e1SPrashanth Swaminathan long FFI_HIDDEN
ffi_closure_SYSV_inner(ffi_closure * closure,void ** values,void * rvalue)251*1fd5a2e1SPrashanth Swaminathan ffi_closure_SYSV_inner(ffi_closure *closure, void **values, void *rvalue)
252*1fd5a2e1SPrashanth Swaminathan {
253*1fd5a2e1SPrashanth Swaminathan ffi_cif *cif;
254*1fd5a2e1SPrashanth Swaminathan ffi_type **arg_types;
255*1fd5a2e1SPrashanth Swaminathan void **avalue;
256*1fd5a2e1SPrashanth Swaminathan int i, areg;
257*1fd5a2e1SPrashanth Swaminathan
258*1fd5a2e1SPrashanth Swaminathan cif = closure->cif;
259*1fd5a2e1SPrashanth Swaminathan if (cif->abi != FFI_SYSV)
260*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
261*1fd5a2e1SPrashanth Swaminathan
262*1fd5a2e1SPrashanth Swaminathan areg = 0;
263*1fd5a2e1SPrashanth Swaminathan
264*1fd5a2e1SPrashanth Swaminathan int rtype = cif->rtype->type;
265*1fd5a2e1SPrashanth Swaminathan if (rtype == FFI_TYPE_STRUCT && cif->rtype->size > 4 * 4)
266*1fd5a2e1SPrashanth Swaminathan {
267*1fd5a2e1SPrashanth Swaminathan rvalue = *values;
268*1fd5a2e1SPrashanth Swaminathan areg++;
269*1fd5a2e1SPrashanth Swaminathan }
270*1fd5a2e1SPrashanth Swaminathan
271*1fd5a2e1SPrashanth Swaminathan cif = closure->cif;
272*1fd5a2e1SPrashanth Swaminathan arg_types = cif->arg_types;
273*1fd5a2e1SPrashanth Swaminathan avalue = alloca(cif->nargs * sizeof(void *));
274*1fd5a2e1SPrashanth Swaminathan
275*1fd5a2e1SPrashanth Swaminathan for (i = 0; i < cif->nargs; i++)
276*1fd5a2e1SPrashanth Swaminathan {
277*1fd5a2e1SPrashanth Swaminathan if (arg_types[i]->alignment == 8 && (areg & 1) != 0)
278*1fd5a2e1SPrashanth Swaminathan areg++;
279*1fd5a2e1SPrashanth Swaminathan
280*1fd5a2e1SPrashanth Swaminathan // skip the entry 16,a1 framework, add 16 bytes (4 registers)
281*1fd5a2e1SPrashanth Swaminathan if (areg == FFI_REGISTER_NARGS)
282*1fd5a2e1SPrashanth Swaminathan areg += 4;
283*1fd5a2e1SPrashanth Swaminathan
284*1fd5a2e1SPrashanth Swaminathan if (arg_types[i]->type == FFI_TYPE_STRUCT)
285*1fd5a2e1SPrashanth Swaminathan {
286*1fd5a2e1SPrashanth Swaminathan int numregs = ((arg_types[i]->size + 3) & ~3) / 4;
287*1fd5a2e1SPrashanth Swaminathan if (areg < FFI_REGISTER_NARGS && areg + numregs > FFI_REGISTER_NARGS)
288*1fd5a2e1SPrashanth Swaminathan areg = FFI_REGISTER_NARGS + 4;
289*1fd5a2e1SPrashanth Swaminathan }
290*1fd5a2e1SPrashanth Swaminathan
291*1fd5a2e1SPrashanth Swaminathan avalue[i] = &values[areg];
292*1fd5a2e1SPrashanth Swaminathan areg += (arg_types[i]->size + 3) / 4;
293*1fd5a2e1SPrashanth Swaminathan }
294*1fd5a2e1SPrashanth Swaminathan
295*1fd5a2e1SPrashanth Swaminathan (closure->fun)(cif, rvalue, avalue, closure->user_data);
296*1fd5a2e1SPrashanth Swaminathan
297*1fd5a2e1SPrashanth Swaminathan return rtype;
298*1fd5a2e1SPrashanth Swaminathan }
299