1*1fd5a2e1SPrashanth Swaminathan /* -----------------------------------------------------------------------
2*1fd5a2e1SPrashanth Swaminathan ffi.c - Copyright (C) 2004 Anthony Green
3*1fd5a2e1SPrashanth Swaminathan Copyright (C) 2007 Free Software Foundation, Inc.
4*1fd5a2e1SPrashanth Swaminathan Copyright (C) 2008 Red Hat, Inc.
5*1fd5a2e1SPrashanth Swaminathan
6*1fd5a2e1SPrashanth Swaminathan FR-V 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
34*1fd5a2e1SPrashanth Swaminathan /* ffi_prep_args is called by the assembly routine once stack space
35*1fd5a2e1SPrashanth Swaminathan has been allocated for the function's arguments */
36*1fd5a2e1SPrashanth Swaminathan
ffi_prep_args(char * stack,extended_cif * ecif)37*1fd5a2e1SPrashanth Swaminathan void *ffi_prep_args(char *stack, extended_cif *ecif)
38*1fd5a2e1SPrashanth Swaminathan {
39*1fd5a2e1SPrashanth Swaminathan register unsigned int i;
40*1fd5a2e1SPrashanth Swaminathan register void **p_argv;
41*1fd5a2e1SPrashanth Swaminathan register char *argp;
42*1fd5a2e1SPrashanth Swaminathan register ffi_type **p_arg;
43*1fd5a2e1SPrashanth Swaminathan register int count = 0;
44*1fd5a2e1SPrashanth Swaminathan
45*1fd5a2e1SPrashanth Swaminathan p_argv = ecif->avalue;
46*1fd5a2e1SPrashanth Swaminathan argp = stack;
47*1fd5a2e1SPrashanth Swaminathan
48*1fd5a2e1SPrashanth Swaminathan for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
49*1fd5a2e1SPrashanth Swaminathan (i != 0);
50*1fd5a2e1SPrashanth Swaminathan i--, p_arg++)
51*1fd5a2e1SPrashanth Swaminathan {
52*1fd5a2e1SPrashanth Swaminathan size_t z;
53*1fd5a2e1SPrashanth Swaminathan
54*1fd5a2e1SPrashanth Swaminathan z = (*p_arg)->size;
55*1fd5a2e1SPrashanth Swaminathan
56*1fd5a2e1SPrashanth Swaminathan if ((*p_arg)->type == FFI_TYPE_STRUCT)
57*1fd5a2e1SPrashanth Swaminathan {
58*1fd5a2e1SPrashanth Swaminathan z = sizeof(void*);
59*1fd5a2e1SPrashanth Swaminathan *(void **) argp = *p_argv;
60*1fd5a2e1SPrashanth Swaminathan }
61*1fd5a2e1SPrashanth Swaminathan /* if ((*p_arg)->type == FFI_TYPE_FLOAT)
62*1fd5a2e1SPrashanth Swaminathan {
63*1fd5a2e1SPrashanth Swaminathan if (count > 24)
64*1fd5a2e1SPrashanth Swaminathan {
65*1fd5a2e1SPrashanth Swaminathan // This is going on the stack. Turn it into a double.
66*1fd5a2e1SPrashanth Swaminathan *(double *) argp = (double) *(float*)(* p_argv);
67*1fd5a2e1SPrashanth Swaminathan z = sizeof(double);
68*1fd5a2e1SPrashanth Swaminathan }
69*1fd5a2e1SPrashanth Swaminathan else
70*1fd5a2e1SPrashanth Swaminathan *(void **) argp = *(void **)(* p_argv);
71*1fd5a2e1SPrashanth Swaminathan } */
72*1fd5a2e1SPrashanth Swaminathan else if (z < sizeof(int))
73*1fd5a2e1SPrashanth Swaminathan {
74*1fd5a2e1SPrashanth Swaminathan z = sizeof(int);
75*1fd5a2e1SPrashanth Swaminathan switch ((*p_arg)->type)
76*1fd5a2e1SPrashanth Swaminathan {
77*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
78*1fd5a2e1SPrashanth Swaminathan *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
79*1fd5a2e1SPrashanth Swaminathan break;
80*1fd5a2e1SPrashanth Swaminathan
81*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
82*1fd5a2e1SPrashanth Swaminathan *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
83*1fd5a2e1SPrashanth Swaminathan break;
84*1fd5a2e1SPrashanth Swaminathan
85*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
86*1fd5a2e1SPrashanth Swaminathan *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
87*1fd5a2e1SPrashanth Swaminathan break;
88*1fd5a2e1SPrashanth Swaminathan
89*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
90*1fd5a2e1SPrashanth Swaminathan *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
91*1fd5a2e1SPrashanth Swaminathan break;
92*1fd5a2e1SPrashanth Swaminathan
93*1fd5a2e1SPrashanth Swaminathan default:
94*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(0);
95*1fd5a2e1SPrashanth Swaminathan }
96*1fd5a2e1SPrashanth Swaminathan }
97*1fd5a2e1SPrashanth Swaminathan else if (z == sizeof(int))
98*1fd5a2e1SPrashanth Swaminathan {
99*1fd5a2e1SPrashanth Swaminathan *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
100*1fd5a2e1SPrashanth Swaminathan }
101*1fd5a2e1SPrashanth Swaminathan else
102*1fd5a2e1SPrashanth Swaminathan {
103*1fd5a2e1SPrashanth Swaminathan memcpy(argp, *p_argv, z);
104*1fd5a2e1SPrashanth Swaminathan }
105*1fd5a2e1SPrashanth Swaminathan p_argv++;
106*1fd5a2e1SPrashanth Swaminathan argp += z;
107*1fd5a2e1SPrashanth Swaminathan count += z;
108*1fd5a2e1SPrashanth Swaminathan }
109*1fd5a2e1SPrashanth Swaminathan
110*1fd5a2e1SPrashanth Swaminathan return (stack + ((count > 24) ? 24 : FFI_ALIGN_DOWN(count, 8)));
111*1fd5a2e1SPrashanth Swaminathan }
112*1fd5a2e1SPrashanth Swaminathan
113*1fd5a2e1SPrashanth Swaminathan /* Perform machine dependent cif processing */
ffi_prep_cif_machdep(ffi_cif * cif)114*1fd5a2e1SPrashanth Swaminathan ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
115*1fd5a2e1SPrashanth Swaminathan {
116*1fd5a2e1SPrashanth Swaminathan if (cif->rtype->type == FFI_TYPE_STRUCT)
117*1fd5a2e1SPrashanth Swaminathan cif->flags = -1;
118*1fd5a2e1SPrashanth Swaminathan else
119*1fd5a2e1SPrashanth Swaminathan cif->flags = cif->rtype->size;
120*1fd5a2e1SPrashanth Swaminathan
121*1fd5a2e1SPrashanth Swaminathan cif->bytes = FFI_ALIGN (cif->bytes, 8);
122*1fd5a2e1SPrashanth Swaminathan
123*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
124*1fd5a2e1SPrashanth Swaminathan }
125*1fd5a2e1SPrashanth Swaminathan
126*1fd5a2e1SPrashanth Swaminathan extern void ffi_call_EABI(void *(*)(char *, extended_cif *),
127*1fd5a2e1SPrashanth Swaminathan extended_cif *,
128*1fd5a2e1SPrashanth Swaminathan unsigned, unsigned,
129*1fd5a2e1SPrashanth Swaminathan unsigned *,
130*1fd5a2e1SPrashanth Swaminathan void (*fn)(void));
131*1fd5a2e1SPrashanth Swaminathan
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)132*1fd5a2e1SPrashanth Swaminathan void ffi_call(ffi_cif *cif,
133*1fd5a2e1SPrashanth Swaminathan void (*fn)(void),
134*1fd5a2e1SPrashanth Swaminathan void *rvalue,
135*1fd5a2e1SPrashanth Swaminathan void **avalue)
136*1fd5a2e1SPrashanth Swaminathan {
137*1fd5a2e1SPrashanth Swaminathan extended_cif ecif;
138*1fd5a2e1SPrashanth Swaminathan
139*1fd5a2e1SPrashanth Swaminathan ecif.cif = cif;
140*1fd5a2e1SPrashanth Swaminathan ecif.avalue = avalue;
141*1fd5a2e1SPrashanth Swaminathan
142*1fd5a2e1SPrashanth Swaminathan /* If the return value is a struct and we don't have a return */
143*1fd5a2e1SPrashanth Swaminathan /* value address then we need to make one */
144*1fd5a2e1SPrashanth Swaminathan
145*1fd5a2e1SPrashanth Swaminathan if ((rvalue == NULL) &&
146*1fd5a2e1SPrashanth Swaminathan (cif->rtype->type == FFI_TYPE_STRUCT))
147*1fd5a2e1SPrashanth Swaminathan {
148*1fd5a2e1SPrashanth Swaminathan ecif.rvalue = alloca(cif->rtype->size);
149*1fd5a2e1SPrashanth Swaminathan }
150*1fd5a2e1SPrashanth Swaminathan else
151*1fd5a2e1SPrashanth Swaminathan ecif.rvalue = rvalue;
152*1fd5a2e1SPrashanth Swaminathan
153*1fd5a2e1SPrashanth Swaminathan
154*1fd5a2e1SPrashanth Swaminathan switch (cif->abi)
155*1fd5a2e1SPrashanth Swaminathan {
156*1fd5a2e1SPrashanth Swaminathan case FFI_EABI:
157*1fd5a2e1SPrashanth Swaminathan ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes,
158*1fd5a2e1SPrashanth Swaminathan cif->flags, ecif.rvalue, fn);
159*1fd5a2e1SPrashanth Swaminathan break;
160*1fd5a2e1SPrashanth Swaminathan default:
161*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(0);
162*1fd5a2e1SPrashanth Swaminathan break;
163*1fd5a2e1SPrashanth Swaminathan }
164*1fd5a2e1SPrashanth Swaminathan }
165*1fd5a2e1SPrashanth Swaminathan
ffi_closure_eabi(unsigned arg1,unsigned arg2,unsigned arg3,unsigned arg4,unsigned arg5,unsigned arg6)166*1fd5a2e1SPrashanth Swaminathan void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
167*1fd5a2e1SPrashanth Swaminathan unsigned arg4, unsigned arg5, unsigned arg6)
168*1fd5a2e1SPrashanth Swaminathan {
169*1fd5a2e1SPrashanth Swaminathan /* This function is called by a trampoline. The trampoline stows a
170*1fd5a2e1SPrashanth Swaminathan pointer to the ffi_closure object in gr7. We must save this
171*1fd5a2e1SPrashanth Swaminathan pointer in a place that will persist while we do our work. */
172*1fd5a2e1SPrashanth Swaminathan register ffi_closure *creg __asm__ ("gr7");
173*1fd5a2e1SPrashanth Swaminathan ffi_closure *closure = creg;
174*1fd5a2e1SPrashanth Swaminathan
175*1fd5a2e1SPrashanth Swaminathan /* Arguments that don't fit in registers are found on the stack
176*1fd5a2e1SPrashanth Swaminathan at a fixed offset above the current frame pointer. */
177*1fd5a2e1SPrashanth Swaminathan register char *frame_pointer __asm__ ("fp");
178*1fd5a2e1SPrashanth Swaminathan char *stack_args = frame_pointer + 16;
179*1fd5a2e1SPrashanth Swaminathan
180*1fd5a2e1SPrashanth Swaminathan /* Lay the register arguments down in a continuous chunk of memory. */
181*1fd5a2e1SPrashanth Swaminathan unsigned register_args[6] =
182*1fd5a2e1SPrashanth Swaminathan { arg1, arg2, arg3, arg4, arg5, arg6 };
183*1fd5a2e1SPrashanth Swaminathan
184*1fd5a2e1SPrashanth Swaminathan ffi_cif *cif = closure->cif;
185*1fd5a2e1SPrashanth Swaminathan ffi_type **arg_types = cif->arg_types;
186*1fd5a2e1SPrashanth Swaminathan void **avalue = alloca (cif->nargs * sizeof(void *));
187*1fd5a2e1SPrashanth Swaminathan char *ptr = (char *) register_args;
188*1fd5a2e1SPrashanth Swaminathan int i;
189*1fd5a2e1SPrashanth Swaminathan
190*1fd5a2e1SPrashanth Swaminathan /* Find the address of each argument. */
191*1fd5a2e1SPrashanth Swaminathan for (i = 0; i < cif->nargs; i++)
192*1fd5a2e1SPrashanth Swaminathan {
193*1fd5a2e1SPrashanth Swaminathan switch (arg_types[i]->type)
194*1fd5a2e1SPrashanth Swaminathan {
195*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
196*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
197*1fd5a2e1SPrashanth Swaminathan avalue[i] = ptr + 3;
198*1fd5a2e1SPrashanth Swaminathan break;
199*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
200*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
201*1fd5a2e1SPrashanth Swaminathan avalue[i] = ptr + 2;
202*1fd5a2e1SPrashanth Swaminathan break;
203*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
204*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
205*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
206*1fd5a2e1SPrashanth Swaminathan avalue[i] = ptr;
207*1fd5a2e1SPrashanth Swaminathan break;
208*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
209*1fd5a2e1SPrashanth Swaminathan avalue[i] = *(void**)ptr;
210*1fd5a2e1SPrashanth Swaminathan break;
211*1fd5a2e1SPrashanth Swaminathan default:
212*1fd5a2e1SPrashanth Swaminathan /* This is an 8-byte value. */
213*1fd5a2e1SPrashanth Swaminathan avalue[i] = ptr;
214*1fd5a2e1SPrashanth Swaminathan ptr += 4;
215*1fd5a2e1SPrashanth Swaminathan break;
216*1fd5a2e1SPrashanth Swaminathan }
217*1fd5a2e1SPrashanth Swaminathan ptr += 4;
218*1fd5a2e1SPrashanth Swaminathan
219*1fd5a2e1SPrashanth Swaminathan /* If we've handled more arguments than fit in registers,
220*1fd5a2e1SPrashanth Swaminathan start looking at the those passed on the stack. */
221*1fd5a2e1SPrashanth Swaminathan if (ptr == ((char *)register_args + (6*4)))
222*1fd5a2e1SPrashanth Swaminathan ptr = stack_args;
223*1fd5a2e1SPrashanth Swaminathan }
224*1fd5a2e1SPrashanth Swaminathan
225*1fd5a2e1SPrashanth Swaminathan /* Invoke the closure. */
226*1fd5a2e1SPrashanth Swaminathan if (cif->rtype->type == FFI_TYPE_STRUCT)
227*1fd5a2e1SPrashanth Swaminathan {
228*1fd5a2e1SPrashanth Swaminathan /* The caller allocates space for the return structure, and
229*1fd5a2e1SPrashanth Swaminathan passes a pointer to this space in gr3. Use this value directly
230*1fd5a2e1SPrashanth Swaminathan as the return value. */
231*1fd5a2e1SPrashanth Swaminathan register void *return_struct_ptr __asm__("gr3");
232*1fd5a2e1SPrashanth Swaminathan (closure->fun) (cif, return_struct_ptr, avalue, closure->user_data);
233*1fd5a2e1SPrashanth Swaminathan }
234*1fd5a2e1SPrashanth Swaminathan else
235*1fd5a2e1SPrashanth Swaminathan {
236*1fd5a2e1SPrashanth Swaminathan /* Allocate space for the return value and call the function. */
237*1fd5a2e1SPrashanth Swaminathan long long rvalue;
238*1fd5a2e1SPrashanth Swaminathan (closure->fun) (cif, &rvalue, avalue, closure->user_data);
239*1fd5a2e1SPrashanth Swaminathan
240*1fd5a2e1SPrashanth Swaminathan /* Functions return 4-byte or smaller results in gr8. 8-byte
241*1fd5a2e1SPrashanth Swaminathan values also use gr9. We fill the both, even for small return
242*1fd5a2e1SPrashanth Swaminathan values, just to avoid a branch. */
243*1fd5a2e1SPrashanth Swaminathan asm ("ldi @(%0, #0), gr8" : : "r" (&rvalue));
244*1fd5a2e1SPrashanth Swaminathan asm ("ldi @(%0, #0), gr9" : : "r" (&((int *) &rvalue)[1]));
245*1fd5a2e1SPrashanth Swaminathan }
246*1fd5a2e1SPrashanth Swaminathan }
247*1fd5a2e1SPrashanth Swaminathan
248*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)249*1fd5a2e1SPrashanth Swaminathan ffi_prep_closure_loc (ffi_closure* closure,
250*1fd5a2e1SPrashanth Swaminathan ffi_cif* cif,
251*1fd5a2e1SPrashanth Swaminathan void (*fun)(ffi_cif*, void*, void**, void*),
252*1fd5a2e1SPrashanth Swaminathan void *user_data,
253*1fd5a2e1SPrashanth Swaminathan void *codeloc)
254*1fd5a2e1SPrashanth Swaminathan {
255*1fd5a2e1SPrashanth Swaminathan unsigned int *tramp = (unsigned int *) &closure->tramp[0];
256*1fd5a2e1SPrashanth Swaminathan unsigned long fn = (long) ffi_closure_eabi;
257*1fd5a2e1SPrashanth Swaminathan unsigned long cls = (long) codeloc;
258*1fd5a2e1SPrashanth Swaminathan #ifdef __FRV_FDPIC__
259*1fd5a2e1SPrashanth Swaminathan register void *got __asm__("gr15");
260*1fd5a2e1SPrashanth Swaminathan #endif
261*1fd5a2e1SPrashanth Swaminathan int i;
262*1fd5a2e1SPrashanth Swaminathan
263*1fd5a2e1SPrashanth Swaminathan fn = (unsigned long) ffi_closure_eabi;
264*1fd5a2e1SPrashanth Swaminathan
265*1fd5a2e1SPrashanth Swaminathan #ifdef __FRV_FDPIC__
266*1fd5a2e1SPrashanth Swaminathan tramp[0] = &((unsigned int *)codeloc)[2];
267*1fd5a2e1SPrashanth Swaminathan tramp[1] = got;
268*1fd5a2e1SPrashanth Swaminathan tramp[2] = 0x8cfc0000 + (fn & 0xffff); /* setlos lo(fn), gr6 */
269*1fd5a2e1SPrashanth Swaminathan tramp[3] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7 */
270*1fd5a2e1SPrashanth Swaminathan tramp[4] = 0x8cf80000 + (fn >> 16); /* sethi hi(fn), gr6 */
271*1fd5a2e1SPrashanth Swaminathan tramp[5] = 0x8ef80000 + (cls >> 16); /* sethi hi(cls), gr7 */
272*1fd5a2e1SPrashanth Swaminathan tramp[6] = 0x9cc86000; /* ldi @(gr6, #0), gr14 */
273*1fd5a2e1SPrashanth Swaminathan tramp[7] = 0x8030e000; /* jmpl @(gr14, gr0) */
274*1fd5a2e1SPrashanth Swaminathan #else
275*1fd5a2e1SPrashanth Swaminathan tramp[0] = 0x8cfc0000 + (fn & 0xffff); /* setlos lo(fn), gr6 */
276*1fd5a2e1SPrashanth Swaminathan tramp[1] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7 */
277*1fd5a2e1SPrashanth Swaminathan tramp[2] = 0x8cf80000 + (fn >> 16); /* sethi hi(fn), gr6 */
278*1fd5a2e1SPrashanth Swaminathan tramp[3] = 0x8ef80000 + (cls >> 16); /* sethi hi(cls), gr7 */
279*1fd5a2e1SPrashanth Swaminathan tramp[4] = 0x80300006; /* jmpl @(gr0, gr6) */
280*1fd5a2e1SPrashanth Swaminathan #endif
281*1fd5a2e1SPrashanth Swaminathan
282*1fd5a2e1SPrashanth Swaminathan closure->cif = cif;
283*1fd5a2e1SPrashanth Swaminathan closure->fun = fun;
284*1fd5a2e1SPrashanth Swaminathan closure->user_data = user_data;
285*1fd5a2e1SPrashanth Swaminathan
286*1fd5a2e1SPrashanth Swaminathan /* Cache flushing. */
287*1fd5a2e1SPrashanth Swaminathan for (i = 0; i < FFI_TRAMPOLINE_SIZE; i++)
288*1fd5a2e1SPrashanth Swaminathan __asm__ volatile ("dcf @(%0,%1)\n\tici @(%2,%1)" :: "r" (tramp), "r" (i),
289*1fd5a2e1SPrashanth Swaminathan "r" (codeloc));
290*1fd5a2e1SPrashanth Swaminathan
291*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
292*1fd5a2e1SPrashanth Swaminathan }
293