1*1fd5a2e1SPrashanth Swaminathan /* libffi support for Altera Nios II.
2*1fd5a2e1SPrashanth Swaminathan
3*1fd5a2e1SPrashanth Swaminathan Copyright (c) 2013 Mentor Graphics.
4*1fd5a2e1SPrashanth Swaminathan
5*1fd5a2e1SPrashanth Swaminathan Permission is hereby granted, free of charge, to any person obtaining
6*1fd5a2e1SPrashanth Swaminathan a copy of this software and associated documentation files (the
7*1fd5a2e1SPrashanth Swaminathan ``Software''), to deal in the Software without restriction, including
8*1fd5a2e1SPrashanth Swaminathan without limitation the rights to use, copy, modify, merge, publish,
9*1fd5a2e1SPrashanth Swaminathan distribute, sublicense, and/or sell copies of the Software, and to
10*1fd5a2e1SPrashanth Swaminathan permit persons to whom the Software is furnished to do so, subject to
11*1fd5a2e1SPrashanth Swaminathan the following conditions:
12*1fd5a2e1SPrashanth Swaminathan
13*1fd5a2e1SPrashanth Swaminathan The above copyright notice and this permission notice shall be
14*1fd5a2e1SPrashanth Swaminathan included in all copies or substantial portions of the Software.
15*1fd5a2e1SPrashanth Swaminathan
16*1fd5a2e1SPrashanth Swaminathan THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
17*1fd5a2e1SPrashanth Swaminathan EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18*1fd5a2e1SPrashanth Swaminathan MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19*1fd5a2e1SPrashanth Swaminathan IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20*1fd5a2e1SPrashanth Swaminathan CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21*1fd5a2e1SPrashanth Swaminathan TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22*1fd5a2e1SPrashanth Swaminathan SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
23*1fd5a2e1SPrashanth Swaminathan
24*1fd5a2e1SPrashanth Swaminathan
25*1fd5a2e1SPrashanth Swaminathan #include <ffi.h>
26*1fd5a2e1SPrashanth Swaminathan #include <ffi_common.h>
27*1fd5a2e1SPrashanth Swaminathan
28*1fd5a2e1SPrashanth Swaminathan #include <stdlib.h>
29*1fd5a2e1SPrashanth Swaminathan
30*1fd5a2e1SPrashanth Swaminathan /* The Nios II Processor Reference Handbook defines the procedure call
31*1fd5a2e1SPrashanth Swaminathan ABI as follows.
32*1fd5a2e1SPrashanth Swaminathan
33*1fd5a2e1SPrashanth Swaminathan Arguments are passed as if a structure containing the types of
34*1fd5a2e1SPrashanth Swaminathan the arguments were constructed. The first 16 bytes are passed in r4
35*1fd5a2e1SPrashanth Swaminathan through r7, the remainder on the stack. The first 16 bytes of a function
36*1fd5a2e1SPrashanth Swaminathan taking variable arguments are passed in r4-r7 in the same way.
37*1fd5a2e1SPrashanth Swaminathan
38*1fd5a2e1SPrashanth Swaminathan Return values of types up to 8 bytes are returned in r2 and r3. For
39*1fd5a2e1SPrashanth Swaminathan return values greater than 8 bytes, the caller must allocate memory for
40*1fd5a2e1SPrashanth Swaminathan the result and pass the address as if it were argument 0.
41*1fd5a2e1SPrashanth Swaminathan
42*1fd5a2e1SPrashanth Swaminathan While this isn't specified explicitly in the ABI documentation, GCC
43*1fd5a2e1SPrashanth Swaminathan promotes integral arguments smaller than int size to 32 bits.
44*1fd5a2e1SPrashanth Swaminathan
45*1fd5a2e1SPrashanth Swaminathan Also of note, the ABI specifies that all structure objects are
46*1fd5a2e1SPrashanth Swaminathan aligned to 32 bits even if all their fields have a smaller natural
47*1fd5a2e1SPrashanth Swaminathan alignment. See FFI_AGGREGATE_ALIGNMENT. */
48*1fd5a2e1SPrashanth Swaminathan
49*1fd5a2e1SPrashanth Swaminathan
50*1fd5a2e1SPrashanth Swaminathan /* Declare the assembly language hooks. */
51*1fd5a2e1SPrashanth Swaminathan
52*1fd5a2e1SPrashanth Swaminathan extern UINT64 ffi_call_sysv (void (*) (char *, extended_cif *),
53*1fd5a2e1SPrashanth Swaminathan extended_cif *,
54*1fd5a2e1SPrashanth Swaminathan unsigned,
55*1fd5a2e1SPrashanth Swaminathan void (*fn) (void));
56*1fd5a2e1SPrashanth Swaminathan extern void ffi_closure_sysv (void);
57*1fd5a2e1SPrashanth Swaminathan
58*1fd5a2e1SPrashanth Swaminathan /* Perform machine-dependent cif processing. */
59*1fd5a2e1SPrashanth Swaminathan
ffi_prep_cif_machdep(ffi_cif * cif)60*1fd5a2e1SPrashanth Swaminathan ffi_status ffi_prep_cif_machdep (ffi_cif *cif)
61*1fd5a2e1SPrashanth Swaminathan {
62*1fd5a2e1SPrashanth Swaminathan /* We always want at least 16 bytes in the parameter block since it
63*1fd5a2e1SPrashanth Swaminathan simplifies the low-level call function. Also round the parameter
64*1fd5a2e1SPrashanth Swaminathan block size up to a multiple of 4 bytes to preserve
65*1fd5a2e1SPrashanth Swaminathan 32-bit alignment of the stack pointer. */
66*1fd5a2e1SPrashanth Swaminathan if (cif->bytes < 16)
67*1fd5a2e1SPrashanth Swaminathan cif->bytes = 16;
68*1fd5a2e1SPrashanth Swaminathan else
69*1fd5a2e1SPrashanth Swaminathan cif->bytes = (cif->bytes + 3) & ~3;
70*1fd5a2e1SPrashanth Swaminathan
71*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
72*1fd5a2e1SPrashanth Swaminathan }
73*1fd5a2e1SPrashanth Swaminathan
74*1fd5a2e1SPrashanth Swaminathan
75*1fd5a2e1SPrashanth Swaminathan /* ffi_prep_args is called by the assembly routine to transfer arguments
76*1fd5a2e1SPrashanth Swaminathan to the stack using the pointers in the ecif array.
77*1fd5a2e1SPrashanth Swaminathan Note that the stack buffer is big enough to fit all the arguments,
78*1fd5a2e1SPrashanth Swaminathan but the first 16 bytes will be copied to registers for the actual
79*1fd5a2e1SPrashanth Swaminathan call. */
80*1fd5a2e1SPrashanth Swaminathan
ffi_prep_args(char * stack,extended_cif * ecif)81*1fd5a2e1SPrashanth Swaminathan void ffi_prep_args (char *stack, extended_cif *ecif)
82*1fd5a2e1SPrashanth Swaminathan {
83*1fd5a2e1SPrashanth Swaminathan char *argp = stack;
84*1fd5a2e1SPrashanth Swaminathan unsigned int i;
85*1fd5a2e1SPrashanth Swaminathan
86*1fd5a2e1SPrashanth Swaminathan /* The implicit return value pointer is passed as if it were a hidden
87*1fd5a2e1SPrashanth Swaminathan first argument. */
88*1fd5a2e1SPrashanth Swaminathan if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
89*1fd5a2e1SPrashanth Swaminathan && ecif->cif->rtype->size > 8)
90*1fd5a2e1SPrashanth Swaminathan {
91*1fd5a2e1SPrashanth Swaminathan (*(void **) argp) = ecif->rvalue;
92*1fd5a2e1SPrashanth Swaminathan argp += 4;
93*1fd5a2e1SPrashanth Swaminathan }
94*1fd5a2e1SPrashanth Swaminathan
95*1fd5a2e1SPrashanth Swaminathan for (i = 0; i < ecif->cif->nargs; i++)
96*1fd5a2e1SPrashanth Swaminathan {
97*1fd5a2e1SPrashanth Swaminathan void *avalue = ecif->avalue[i];
98*1fd5a2e1SPrashanth Swaminathan ffi_type *atype = ecif->cif->arg_types[i];
99*1fd5a2e1SPrashanth Swaminathan size_t size = atype->size;
100*1fd5a2e1SPrashanth Swaminathan size_t alignment = atype->alignment;
101*1fd5a2e1SPrashanth Swaminathan
102*1fd5a2e1SPrashanth Swaminathan /* Align argp as appropriate for the argument type. */
103*1fd5a2e1SPrashanth Swaminathan if ((alignment - 1) & (unsigned) argp)
104*1fd5a2e1SPrashanth Swaminathan argp = (char *) FFI_ALIGN (argp, alignment);
105*1fd5a2e1SPrashanth Swaminathan
106*1fd5a2e1SPrashanth Swaminathan /* Copy the argument, promoting integral types smaller than a
107*1fd5a2e1SPrashanth Swaminathan word to word size. */
108*1fd5a2e1SPrashanth Swaminathan if (size < sizeof (int))
109*1fd5a2e1SPrashanth Swaminathan {
110*1fd5a2e1SPrashanth Swaminathan size = sizeof (int);
111*1fd5a2e1SPrashanth Swaminathan switch (atype->type)
112*1fd5a2e1SPrashanth Swaminathan {
113*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
114*1fd5a2e1SPrashanth Swaminathan *(signed int *) argp = (signed int) *(SINT8 *) avalue;
115*1fd5a2e1SPrashanth Swaminathan break;
116*1fd5a2e1SPrashanth Swaminathan
117*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
118*1fd5a2e1SPrashanth Swaminathan *(unsigned int *) argp = (unsigned int) *(UINT8 *) avalue;
119*1fd5a2e1SPrashanth Swaminathan break;
120*1fd5a2e1SPrashanth Swaminathan
121*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
122*1fd5a2e1SPrashanth Swaminathan *(signed int *) argp = (signed int) *(SINT16 *) avalue;
123*1fd5a2e1SPrashanth Swaminathan break;
124*1fd5a2e1SPrashanth Swaminathan
125*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
126*1fd5a2e1SPrashanth Swaminathan *(unsigned int *) argp = (unsigned int) *(UINT16 *) avalue;
127*1fd5a2e1SPrashanth Swaminathan break;
128*1fd5a2e1SPrashanth Swaminathan
129*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
130*1fd5a2e1SPrashanth Swaminathan memcpy (argp, avalue, atype->size);
131*1fd5a2e1SPrashanth Swaminathan break;
132*1fd5a2e1SPrashanth Swaminathan
133*1fd5a2e1SPrashanth Swaminathan default:
134*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(0);
135*1fd5a2e1SPrashanth Swaminathan }
136*1fd5a2e1SPrashanth Swaminathan }
137*1fd5a2e1SPrashanth Swaminathan else if (size == sizeof (int))
138*1fd5a2e1SPrashanth Swaminathan *(unsigned int *) argp = (unsigned int) *(UINT32 *) avalue;
139*1fd5a2e1SPrashanth Swaminathan else
140*1fd5a2e1SPrashanth Swaminathan memcpy (argp, avalue, size);
141*1fd5a2e1SPrashanth Swaminathan argp += size;
142*1fd5a2e1SPrashanth Swaminathan }
143*1fd5a2e1SPrashanth Swaminathan }
144*1fd5a2e1SPrashanth Swaminathan
145*1fd5a2e1SPrashanth Swaminathan
146*1fd5a2e1SPrashanth Swaminathan /* Call FN using the prepared CIF. RVALUE points to space allocated by
147*1fd5a2e1SPrashanth Swaminathan the caller for the return value, and AVALUE is an array of argument
148*1fd5a2e1SPrashanth Swaminathan pointers. */
149*1fd5a2e1SPrashanth Swaminathan
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)150*1fd5a2e1SPrashanth Swaminathan void ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
151*1fd5a2e1SPrashanth Swaminathan {
152*1fd5a2e1SPrashanth Swaminathan
153*1fd5a2e1SPrashanth Swaminathan extended_cif ecif;
154*1fd5a2e1SPrashanth Swaminathan UINT64 result;
155*1fd5a2e1SPrashanth Swaminathan
156*1fd5a2e1SPrashanth Swaminathan /* If bigret is true, this is the case where a return value of larger
157*1fd5a2e1SPrashanth Swaminathan than 8 bytes is handled by being passed by reference as an implicit
158*1fd5a2e1SPrashanth Swaminathan argument. */
159*1fd5a2e1SPrashanth Swaminathan int bigret = (cif->rtype->type == FFI_TYPE_STRUCT
160*1fd5a2e1SPrashanth Swaminathan && cif->rtype->size > 8);
161*1fd5a2e1SPrashanth Swaminathan
162*1fd5a2e1SPrashanth Swaminathan ecif.cif = cif;
163*1fd5a2e1SPrashanth Swaminathan ecif.avalue = avalue;
164*1fd5a2e1SPrashanth Swaminathan
165*1fd5a2e1SPrashanth Swaminathan /* Allocate space for return value if this is the pass-by-reference case
166*1fd5a2e1SPrashanth Swaminathan and the caller did not provide a buffer. */
167*1fd5a2e1SPrashanth Swaminathan if (rvalue == NULL && bigret)
168*1fd5a2e1SPrashanth Swaminathan ecif.rvalue = alloca (cif->rtype->size);
169*1fd5a2e1SPrashanth Swaminathan else
170*1fd5a2e1SPrashanth Swaminathan ecif.rvalue = rvalue;
171*1fd5a2e1SPrashanth Swaminathan
172*1fd5a2e1SPrashanth Swaminathan result = ffi_call_sysv (ffi_prep_args, &ecif, cif->bytes, fn);
173*1fd5a2e1SPrashanth Swaminathan
174*1fd5a2e1SPrashanth Swaminathan /* Now result contains the 64 bit contents returned from fn in
175*1fd5a2e1SPrashanth Swaminathan r2 and r3. Copy the value of the appropriate size to the user-provided
176*1fd5a2e1SPrashanth Swaminathan rvalue buffer. */
177*1fd5a2e1SPrashanth Swaminathan if (rvalue && !bigret)
178*1fd5a2e1SPrashanth Swaminathan switch (cif->rtype->size)
179*1fd5a2e1SPrashanth Swaminathan {
180*1fd5a2e1SPrashanth Swaminathan case 1:
181*1fd5a2e1SPrashanth Swaminathan *(UINT8 *)rvalue = (UINT8) result;
182*1fd5a2e1SPrashanth Swaminathan break;
183*1fd5a2e1SPrashanth Swaminathan case 2:
184*1fd5a2e1SPrashanth Swaminathan *(UINT16 *)rvalue = (UINT16) result;
185*1fd5a2e1SPrashanth Swaminathan break;
186*1fd5a2e1SPrashanth Swaminathan case 4:
187*1fd5a2e1SPrashanth Swaminathan *(UINT32 *)rvalue = (UINT32) result;
188*1fd5a2e1SPrashanth Swaminathan break;
189*1fd5a2e1SPrashanth Swaminathan case 8:
190*1fd5a2e1SPrashanth Swaminathan *(UINT64 *)rvalue = (UINT64) result;
191*1fd5a2e1SPrashanth Swaminathan break;
192*1fd5a2e1SPrashanth Swaminathan default:
193*1fd5a2e1SPrashanth Swaminathan memcpy (rvalue, (void *)&result, cif->rtype->size);
194*1fd5a2e1SPrashanth Swaminathan break;
195*1fd5a2e1SPrashanth Swaminathan }
196*1fd5a2e1SPrashanth Swaminathan }
197*1fd5a2e1SPrashanth Swaminathan
198*1fd5a2e1SPrashanth Swaminathan /* This function is invoked from the closure trampoline to invoke
199*1fd5a2e1SPrashanth Swaminathan CLOSURE with argument block ARGS. Parse ARGS according to
200*1fd5a2e1SPrashanth Swaminathan CLOSURE->cfi and invoke CLOSURE->fun. */
201*1fd5a2e1SPrashanth Swaminathan
202*1fd5a2e1SPrashanth Swaminathan static UINT64
ffi_closure_helper(unsigned char * args,ffi_closure * closure)203*1fd5a2e1SPrashanth Swaminathan ffi_closure_helper (unsigned char *args,
204*1fd5a2e1SPrashanth Swaminathan ffi_closure *closure)
205*1fd5a2e1SPrashanth Swaminathan {
206*1fd5a2e1SPrashanth Swaminathan ffi_cif *cif = closure->cif;
207*1fd5a2e1SPrashanth Swaminathan unsigned char *argp = args;
208*1fd5a2e1SPrashanth Swaminathan void **parsed_args = alloca (cif->nargs * sizeof (void *));
209*1fd5a2e1SPrashanth Swaminathan UINT64 result;
210*1fd5a2e1SPrashanth Swaminathan void *retptr;
211*1fd5a2e1SPrashanth Swaminathan unsigned int i;
212*1fd5a2e1SPrashanth Swaminathan
213*1fd5a2e1SPrashanth Swaminathan /* First figure out what to do about the return type. If this is the
214*1fd5a2e1SPrashanth Swaminathan big-structure-return case, the first arg is the hidden return buffer
215*1fd5a2e1SPrashanth Swaminathan allocated by the caller. */
216*1fd5a2e1SPrashanth Swaminathan if (cif->rtype->type == FFI_TYPE_STRUCT
217*1fd5a2e1SPrashanth Swaminathan && cif->rtype->size > 8)
218*1fd5a2e1SPrashanth Swaminathan {
219*1fd5a2e1SPrashanth Swaminathan retptr = *((void **) argp);
220*1fd5a2e1SPrashanth Swaminathan argp += 4;
221*1fd5a2e1SPrashanth Swaminathan }
222*1fd5a2e1SPrashanth Swaminathan else
223*1fd5a2e1SPrashanth Swaminathan retptr = (void *) &result;
224*1fd5a2e1SPrashanth Swaminathan
225*1fd5a2e1SPrashanth Swaminathan /* Fill in the array of argument pointers. */
226*1fd5a2e1SPrashanth Swaminathan for (i = 0; i < cif->nargs; i++)
227*1fd5a2e1SPrashanth Swaminathan {
228*1fd5a2e1SPrashanth Swaminathan size_t size = cif->arg_types[i]->size;
229*1fd5a2e1SPrashanth Swaminathan size_t alignment = cif->arg_types[i]->alignment;
230*1fd5a2e1SPrashanth Swaminathan
231*1fd5a2e1SPrashanth Swaminathan /* Align argp as appropriate for the argument type. */
232*1fd5a2e1SPrashanth Swaminathan if ((alignment - 1) & (unsigned) argp)
233*1fd5a2e1SPrashanth Swaminathan argp = (char *) FFI_ALIGN (argp, alignment);
234*1fd5a2e1SPrashanth Swaminathan
235*1fd5a2e1SPrashanth Swaminathan /* Arguments smaller than an int are promoted to int. */
236*1fd5a2e1SPrashanth Swaminathan if (size < sizeof (int))
237*1fd5a2e1SPrashanth Swaminathan size = sizeof (int);
238*1fd5a2e1SPrashanth Swaminathan
239*1fd5a2e1SPrashanth Swaminathan /* Store the pointer. */
240*1fd5a2e1SPrashanth Swaminathan parsed_args[i] = argp;
241*1fd5a2e1SPrashanth Swaminathan argp += size;
242*1fd5a2e1SPrashanth Swaminathan }
243*1fd5a2e1SPrashanth Swaminathan
244*1fd5a2e1SPrashanth Swaminathan /* Call the user-supplied function. */
245*1fd5a2e1SPrashanth Swaminathan (closure->fun) (cif, retptr, parsed_args, closure->user_data);
246*1fd5a2e1SPrashanth Swaminathan return result;
247*1fd5a2e1SPrashanth Swaminathan }
248*1fd5a2e1SPrashanth Swaminathan
249*1fd5a2e1SPrashanth Swaminathan
250*1fd5a2e1SPrashanth Swaminathan /* Initialize CLOSURE with a trampoline to call FUN with
251*1fd5a2e1SPrashanth Swaminathan CIF and USER_DATA. */
252*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)253*1fd5a2e1SPrashanth Swaminathan ffi_prep_closure_loc (ffi_closure* closure,
254*1fd5a2e1SPrashanth Swaminathan ffi_cif* cif,
255*1fd5a2e1SPrashanth Swaminathan void (*fun) (ffi_cif*, void*, void**, void*),
256*1fd5a2e1SPrashanth Swaminathan void *user_data,
257*1fd5a2e1SPrashanth Swaminathan void *codeloc)
258*1fd5a2e1SPrashanth Swaminathan {
259*1fd5a2e1SPrashanth Swaminathan unsigned int *tramp = (unsigned int *) &closure->tramp[0];
260*1fd5a2e1SPrashanth Swaminathan int i;
261*1fd5a2e1SPrashanth Swaminathan
262*1fd5a2e1SPrashanth Swaminathan if (cif->abi != FFI_SYSV)
263*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
264*1fd5a2e1SPrashanth Swaminathan
265*1fd5a2e1SPrashanth Swaminathan /* The trampoline looks like:
266*1fd5a2e1SPrashanth Swaminathan movhi r8, %hi(ffi_closure_sysv)
267*1fd5a2e1SPrashanth Swaminathan ori r8, r8, %lo(ffi_closure_sysv)
268*1fd5a2e1SPrashanth Swaminathan movhi r9, %hi(ffi_closure_helper)
269*1fd5a2e1SPrashanth Swaminathan ori r0, r9, %lo(ffi_closure_helper)
270*1fd5a2e1SPrashanth Swaminathan movhi r10, %hi(closure)
271*1fd5a2e1SPrashanth Swaminathan ori r10, r10, %lo(closure)
272*1fd5a2e1SPrashanth Swaminathan jmp r8
273*1fd5a2e1SPrashanth Swaminathan and then ffi_closure_sysv retrieves the closure pointer out of r10
274*1fd5a2e1SPrashanth Swaminathan in addition to the arguments passed in the normal way for the call,
275*1fd5a2e1SPrashanth Swaminathan and invokes ffi_closure_helper. We encode the pointer to
276*1fd5a2e1SPrashanth Swaminathan ffi_closure_helper in the trampoline because making a PIC call
277*1fd5a2e1SPrashanth Swaminathan to it in ffi_closure_sysv would be messy (it would have to indirect
278*1fd5a2e1SPrashanth Swaminathan through the GOT). */
279*1fd5a2e1SPrashanth Swaminathan
280*1fd5a2e1SPrashanth Swaminathan #define HI(x) ((((unsigned int) (x)) >> 16) & 0xffff)
281*1fd5a2e1SPrashanth Swaminathan #define LO(x) (((unsigned int) (x)) & 0xffff)
282*1fd5a2e1SPrashanth Swaminathan tramp[0] = (0 << 27) | (8 << 22) | (HI (ffi_closure_sysv) << 6) | 0x34;
283*1fd5a2e1SPrashanth Swaminathan tramp[1] = (8 << 27) | (8 << 22) | (LO (ffi_closure_sysv) << 6) | 0x14;
284*1fd5a2e1SPrashanth Swaminathan tramp[2] = (0 << 27) | (9 << 22) | (HI (ffi_closure_helper) << 6) | 0x34;
285*1fd5a2e1SPrashanth Swaminathan tramp[3] = (9 << 27) | (9 << 22) | (LO (ffi_closure_helper) << 6) | 0x14;
286*1fd5a2e1SPrashanth Swaminathan tramp[4] = (0 << 27) | (10 << 22) | (HI (closure) << 6) | 0x34;
287*1fd5a2e1SPrashanth Swaminathan tramp[5] = (10 << 27) | (10 << 22) | (LO (closure) << 6) | 0x14;
288*1fd5a2e1SPrashanth Swaminathan tramp[6] = (8 << 27) | (0x0d << 11) | 0x3a;
289*1fd5a2e1SPrashanth Swaminathan #undef HI
290*1fd5a2e1SPrashanth Swaminathan #undef LO
291*1fd5a2e1SPrashanth Swaminathan
292*1fd5a2e1SPrashanth Swaminathan /* Flush the caches.
293*1fd5a2e1SPrashanth Swaminathan See Example 9-4 in the Nios II Software Developer's Handbook. */
294*1fd5a2e1SPrashanth Swaminathan for (i = 0; i < 7; i++)
295*1fd5a2e1SPrashanth Swaminathan asm volatile ("flushd 0(%0); flushi %0" :: "r"(tramp + i) : "memory");
296*1fd5a2e1SPrashanth Swaminathan asm volatile ("flushp" ::: "memory");
297*1fd5a2e1SPrashanth Swaminathan
298*1fd5a2e1SPrashanth Swaminathan closure->cif = cif;
299*1fd5a2e1SPrashanth Swaminathan closure->fun = fun;
300*1fd5a2e1SPrashanth Swaminathan closure->user_data = user_data;
301*1fd5a2e1SPrashanth Swaminathan
302*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
303*1fd5a2e1SPrashanth Swaminathan }
304*1fd5a2e1SPrashanth Swaminathan
305